【发布时间】:2015-12-05 22:51:15
【问题描述】:
首先,这是我继承的代码,编写它的人不再在这里,也无法质疑。
我让生产中的用户对随机退出我们的 Asp.Net MVC 应用程序感到恼火(根据参考资料,我们的 MVC 库是第 5 版)。在代码和网站中徘徊了一段时间后,我想我已经将用户看到的内容隔离到以下代码:
public class SessionExpireFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpContext ctx = HttpContext.Current;
// check if session is supported
if (ctx.Session != null)
{
// check if a new session id was generated
if (ctx.Session.IsNewSession)
{
// If it says it is a new session, but an existing cookie exists, then it must
// have timed out
string sessionCookie = ctx.Request.Headers["Cookie"];
if ((null != sessionCookie) && (sessionCookie.IndexOf("ASP.NET_SessionId") >= 0))
{
SessionVariables.Current.User = null;
FormsAuthentication.SignOut();
filterContext.Result = new RedirectResult("~/Account/Logon");
return;
}
}
}
base.OnActionExecuting(filterContext);
}
}
我不完全确定为什么需要此代码(您为什么要将其归因而不是使其全局化),但我在搜索中看到互联网上此代码的变体,但没有说明您想要的原因它。
不管怎样,它已经在我们的代码库中,我们遇到的问题似乎是,如果用户在窗口中闲置一小段时间然后他们做某事,ctx.Session 不为空,而是ctx.Session.IsNewSession 是真的。
这对我来说意味着,出于某种原因,Asp.net 决定该用户需要为他们启动一个全新的会话,并且由于我们不知道该用户是谁(因为他们的所有会话数据都已消失......一个新的会话)我们需要注销他们并让他们重新登录。
这一切似乎都是合乎逻辑的,只是我终于能够在IsNewSession if 语句中打断点。对我来说奇怪的是,我的 Session 实际上看起来 100% 已填写(并且填写正确)。这意味着它正确地知道我是谁,以及只有在您成功登录后才会放入会话中的所有其他信息。
此外,ctx.User.Identity.IsAuthenticated 是真的,它有正确的登录名。
一切似乎都表明我有一个有效的会话,但由于这段代码正在做出设计决定,即如果 Asp.Net 创建一个新会话,我必须注销,用户将被注销。
所以我的问题是:
-
Session.IsNewSession的实际含义是什么? - 当
IsNewSession为真时始终将用户注销是否正确? - 只要用户被列为已通过身份验证并具有有效的会话数据,不注销用户是否有任何后果?
- 是什么导致 Asp.Net 创建新会话但仍重复使用以前的会话数据?
- 我对会话过期的理解是它是由提供程序层引起的,因为如果会话过期,Asp.Net 甚至不会有任何会话数据。不是这样吗?
顺便说一下,我们目前使用 Redis 作为我们的会话存储。此外,如果相关应用程序托管在 Azure 网站上(我不确定这会如何影响会话到期)。
【问题讨论】:
-
简单来说,就是当现有 会话存在但已超时时启动了一个新会话。当包含先前会话的 cookie 被发送回 Web 服务器时,该会话已过期,因此会构建一个新会话(因此 IsNewSession==true),因为该会话 ID 与构建的新会话 ID 不同。
-
我想我应该添加 FormsAuthentication.Timeout 显示 8 小时超时,但 htis 在最初登录后大约 5-10 分钟发生。所以理论上会话不应该在那个时间超时期间对吗?
-
FormsAuthentication 超时与会话超时不同。
-
您是否检查过网站上发生某种错误或内容更改的可能性,其中任何一种都会破坏当前会话?
-
我没有,但这又回到了我最初的问题是,如果前一个会话由于错误或内容更改而超时,我是否应该关心一个新会话?据推测,当这些情况发生时,用户应该保持登录状态,尤其是在进程外会话状态存储(如 redis)的情况下?如果不是 100% 使用此代码,任何负载平衡似乎都会完全破坏用户会话