我正在使用.NET Core 2.1
,并试图将Session用作身份验证的一部分。我期望发生的是:
HttpContext.Session.Clear()
清除了会话然后,我试图伪造一种情况,即会话cookie已经从原始人那里窃取了,因此我向服务器创建了另一个请求,并期望会话中设置的值不存在。甚至在调用Session.Clear()
之后,它看起来仍然保持不变。
代码:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(10);
options.Cookie.Name = SessionCookieName;
options.Cookie.HttpOnly = true;
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseSession();
}
登录操作:
HttpContext.Session.SetInt32(SessionConstants.Key, value);
注销操作:
HttpContext.Session.Clear();
CheckLoginStatus操作:
var sessionValue = HttpContext.Session.GetInt32(SessionConstants.Key);
测试解决问题的方法:
var httpClientGenuineRequest = GetClient();
var httpClientAttacker = GetClient();
//Given
var request = new LoginRequest()
{
//filled properties
};
var loginResponse = await httpClientGenuineMember.PostAsync("urlToLoginAction", new JsonContent(request));
AddResponseCookiesToHeaders(httpClientAttacker, loginResponse);
await httpClientGenuineMember.PostAsync("urlToLogoutAction", new JsonContent(request));
//When
var response = await httpClientAttacker.GetAsync("urlToCheckStatusAction");
//Here the actual result is true
var actualResult = response.GetResult<bool>();
//Then
var expectedResult = false;
以上示例不完整。问题仅与会话值有关,因此我摆脱了所有其他身份验证代码以使其更加清晰。
在我看来,HttpContext.Session.Clear
没有清除会话,或者该值存储在会话Cookie中(没有任何意义)?
此外,当我调试并检查密钥的Session值时,紧接Clear()
之后,它为我提供了null值。但是,当我传递会话cookie并尝试读取该值时,它再次出现。
很明显,当Idle Timeout
用完时,代码将按预期运行。在这段时间内,这听起来像是有一定的安全隐患。
任何帮助将不胜感激。
根据帖子下方的评论,我尝试向其中添加Redis会话:
services.AddDistributedRedisCache(setup =>
{
setup.Configuration = "urlToRedisInstance";
setup.InstanceName = "MySessionStateStore2";
});
但行为完全相同。
答案 0 :(得分:1)
原因是(听起来很荒谬)是因为您没有清除正确的会话变量。
根据Microsoft docs,当发生以下两种情况之一时,.net core 2.1中的会话结束:
在执行ISession.Clear时删除会话数据 或会话期满时被调用。
然后显示以下状态:
没有默认机制来通知应用代码客户端浏览器 已关闭,或者会话cookie被删除或过期 客户。
这告诉我们两件事:
1),如果您想使用会话已过期的最大次数,则必须自行修改 的机制,以在客户端会话过期时通知服务器或浏览器关闭。否则,即使关闭浏览器,您仍可能保留会话数据(这是一种荒谬的情况,但确实存在)。
2) ISession.Clear方法是Microsoft.AspNetCore.Http命名空间的一部分,这意味着当您调用HttpContext.Session.Clear();
时,您基本上可以清除一无所有。
正如我所说,这种情况可能很痛苦,但却是一个鲜活的事实,并且如果我们选择使用.net core 2.1和会话状态,我们的代码必须知道如何处理。
答案 1 :(得分:0)
挖掘代码后,我发现了问题:
问题出在我的测试中。我将登录请求响应cookie设置为“攻击者”的httpClient,而不是实际用户。结果,它没有得到Session Cookie
,因此我的Session.Clear()
实际上清除了新创建的会话,而不是登录过程中创建的会话。
正确的测试:
var httpClientGenuineRequest = GetClient();
var httpClientAttacker = GetClient();
//Given
var request = new LoginRequest()
{
//filled properties
};
var loginResponse = await httpClientGenuineMember.PostAsync("urlToLoginAction", new JsonContent(request));
AddResponseCookiesToHeaders(httpClientGenuineMember, loginResponse); // THAT LINE MADE THE DIFFERENCE
AddResponseCookiesToHeaders(httpClientAttacker, loginResponse);
await httpClientGenuineMember.PostAsync("urlToLogoutAction", new JsonContent(request));
//When
var response = await httpClientAttacker.GetAsync("urlToCheckStatusAction");
//Here the actual result is true
var actualResult = response.GetResult<bool>();
//Then
var expectedResult = false;
Session.Clear()
完全按预期工作。