首先,这是我继承的代码,编写它的人不再在这里,也无法提问.
我的生产中的用户因随机退出我们的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不是null但是ctx.Session .IsNewSession是真的.
这对我来说意味着由于某种原因Asp.net决定这个用户需要为他们启动一个全新的会话,因为我们不知道这个用户是谁(因为他们所有的会话数据都已经消失了……这是一个新的会话)我们需要将它们注销并让它们再次登录.
这一切看似合乎逻辑,除了我最终能够在IsNewSession if语句中找到一个断点.对我来说奇怪的是,我的会话实际上看起来100%填写(并填写正确).这意味着它正确地知道我是谁,以及当您成功登录时才会进入会话的所有其他信息.
此外,ctx.User.Identity.IsAuthenticated为true,并且具有正确的登录名.
一切似乎都表明我有一个有效的会话,但由于这个代码正在做出设计决定,如果Asp.Net创建一个新的会话我必须注销,用户将被注销.
所以我的问题是:
> Session.IsNewSession在实践中意味着什么?
>当IsNewSession为true时,始终将用户注销是否正确?
>只要将用户列为已通过身份验证且具有有效会话数据,是否有任何记录不记录用户?
>是什么原因导致Asp.Net创建新会话但仍然重用以前的会话数据?
>我对会话到期的理解是它是由提供者层引起的,因为如果会话已经过期,Asp.Net甚至不会有任何会话数据.那不是这样吗?
作为快速说明,我们目前正在使用Redis作为会话商店.此外,如果相关应用程序正在Azure网站上托管(我不确定这会如何影响会话到期).
解决方法
只要没有当前会话的浏览器导航到该站点,ASP.NET就会创建一个新的Session.所以即使有人没有登录,他们仍然会有一个会话.同样,如果一个会话到期,则下次浏览器发出请求时将创建一个新会话.此新会话将不会存储“会话数据”,但ctx.Session不会为null.此外,如果您有多个服务器并且负载均衡器恰好将用户路由到其他服务器,则该新服务器将尝试启动新会话.
会话状态与身份验证状态分开跟踪,这意味着一个可以在另一个仍然有效的情况下到期.对于编写良好的应用程序,这通常不会导致任何问题.但是,某些应用程序在登录时会将信息预加载到会话中,并将会话视为会话长度内此信息的一种缓存.或者,当用户执行某些操作时,他们将在会话上设置值,并且稍后的操作将期望这些值在会话上,因为用户应该已经浏览了那些先前的操作以到达那里. (例如,向导界面,其中每个步骤都将值保存到会话中,以便在用户单击最后一步的“完成”时使用.)
您的应用程序可能在某个时刻期望数据存在于不存在的会话中,并且开发人员意识到它不存在,因为ASP.NET已自动更新会话,丢失了所有先前设置的会话数据.他们没有重新设计他们对会话数据的使用,而是选择这样做,以便在他们失去会话的任何时候,他们也会强迫用户回到一个理智的起始位置,页面不会因为会话而以奇怪的方式打破存储的数据丢失了.