7

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

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

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

网络配置

<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>

动作过滤器

[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);
        }
    }
}

全球.ASAX

protected void Session_Start(object sender, EventArgs e)
{
    Session["IsActiveSession"] = DateTime.Now;
}
4

1 回答 1

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);
        }

    }
}

如果您想花哨并确保他们在为此请求创建的新会话之前有一个先前的会话,您可以更新if语句以检查是否与请求一起发送了旧的会话 cookie:

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

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

于 2013-12-06T15:17:18.330 回答