会话开始和操作过滤器用于会话超时处理

LCJ*_*LCJ 7 asp.net-mvc session asp.net-mvc-4

我有一个MVC4应用程序Windows Authentication.用户可以键入10个视图中的任何一个的url来加载应用程序.没有特定的主页

如果用户闲置超过一分钟,我需要重定向到会话超时视图.我将配置文件中的会话超时值保持为一分钟.我创建了一个action filter检查一个特定会话值的方法.此特定会话值设置Session_StartGlobal.asax.

但是,当超时时间结束时,请求再次命中Session_Start并且它正在分配值.因此我的动作过滤器不会重定向到错误视图.有什么可能的解决方案来解决这个问题?

Web.Config中

<system.web>
    <!--Impersonate-->
    <identity impersonate="true"/>
        <!--Session Mode and Timeout-->
    <sessionState mode="InProc" timeout="1" />
    <authentication mode="Windows">
    </authentication>
    <authorization>
      <allow users="?" />
    </authorization>    
</system.web>
Run Code Online (Sandbox Code Playgroud)

动作过滤器

[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class SessionCheckAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(System.Web.Mvc.ActionExecutingContext filterContext)
    {
        string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.ToLower();
        HttpSessionStateBase session = filterContext.HttpContext.Session;
        var activeSession = session["IsActiveSession"];
        if (activeSession == null)
        {
            //Redirect
            var url = new UrlHelper(filterContext.RequestContext);
            var loginUrl = url.Content("~/Error/SessionTimeout");
            filterContext.HttpContext.Response.Redirect(loginUrl, true);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Global.asax中

protected void Session_Start(object sender, EventArgs e)
{
    Session["IsActiveSession"] = DateTime.Now;
}
Run Code Online (Sandbox Code Playgroud)

mar*_*gli 11

只需检查HttpContext.Current.Session.IsNewSession是否为当前请求创建了新会话,而不是设置会话值并在操作过滤器中进行检查.修改你的动作过滤器,你最终会得到这样的结果:

[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class SessionCheckAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(System.Web.Mvc.ActionExecutingContext filterContext)
    {
        string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.ToLower();
        HttpSessionStateBase session = filterContext.HttpContext.Session;
        if (session.IsNewSession)
        {
            //Redirect
            var url = new UrlHelper(filterContext.RequestContext);
            var loginUrl = url.Content("~/Error/SessionTimeout");
            filterContext.HttpContext.Response.Redirect(loginUrl, true);
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

如果您想获得想象并确保在为此请求创建的新会话之前有前一个会话,您可以更新该if语句以检查是否随请求一起发送了旧会话cookie:

string cookieHeader = filterContext.HttpContext.Request.Headers["Cookie"];
if (session.IsNewSession && cookieHeader != null && cookieHeader.IndexOf("ASP.NET_SessionId") >= 0)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

但是因为看起来你正在将它们发送到登录页面,所以这可能不是你在这里需要担心的事情.如果您使用此检查,请注意此代码采用默认"ASP.NET_SessionId"cookie名称; 这可以在web.config中更改,在这种情况下,您需要IndexOf使用新的cookie名称更新参数或以编程方式获取cookie名称.

  • 谢谢,我已经取代了它. (2认同)