MVC3 Session timeout after 10 seconds

2019-06-02 10:55发布

问题:

Need some help with a Session timeout problem in an ASP.Net web app. Essentially the session expires about 10-15 seconds after login.

Side Note: I use a custom combo of FormsAuthentication and basic security

My Session.IsNewSession gets set to true after 3-4 good postbacks after login.

My Web.Config has the following...

<sessionState mode="InProc" timeout="130" regenerateExpiredSessionId="true" stateNetworkTimeout="120" compressionEnabled="true" cookieless="UseCookies" />
<authentication mode="Forms">
  <forms timeout="120" ticketCompatibilityMode="Framework40" enableCrossAppRedirects="true" />
</authentication>

Where I believe the timeout refers to minutes....

I have an MVC 3 application with an ActionFilter registered

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new MyActionFilterAttribute());
    }

Inside the OnActionExecuting I check for a Current Session to prevent access to controller actions which an unauthorized user shouldn't be able to access.

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {            
        HttpContext ctx = HttpContext.Current;

        Player player = SessionHelper.GetCurrentPlayer(filterContext.HttpContext.Session);

        if (player == null && ctx != null)
        {
            player = SessionHelper.GetCurrentPlayer(ctx.Session);
        }

        if (player == null ||
            (player.IsAdministrator == false && player.IsCoach == false && player.IsCommittee == false))
        {
            if (filterContext.Controller is HomeController || filterContext.Controller is AccountController)
            {
                base.OnActionExecuting(filterContext);
                return;
            }

            string ctxError = ctx != null ? "Context Exists" : "Context Doesnt Exist";
            string sessionError = filterContext.HttpContext.Session != null ? "filterContext.HttpContext.Session Exists" : "filterContext.HttpContext.Session Doesnt Exist";
            string requestSessionError = filterContext.RequestContext.HttpContext.Session != null ? "filterContext.RequestContext.HttpContext.Session Exists" : "filterContext.RequestContext.HttpContext.Session Doesnt Exist";

            throw new SecurityException(string.Format("Attempt to access {0} by user at {1} - {2} ({3}, {4}, {5})",
                                                      filterContext.HttpContext.Request.RawUrl,
                                                      filterContext.HttpContext.Request.UserHostAddress,
                                                      filterContext.HttpContext.Session,
                                                      ctxError,
                                                      sessionError,
                                                      requestSessionError));
        }

        base.OnActionExecuting(filterContext);
    }

回答1:

So I've determined that the Web Server was refreshing its AppPool faster than my session lifespan. This would result in the same SessionId to be used, but the IsNewSession flag to be set also.

As I have no control over the AppPool lifespan I was able to keep the session in the InProc mode in IIS.

I resolved the issue by moving Session State persistance to a hosted SqlServer database, thereby allowing the session to persist despite the AppPool being recycled.

I'd recommend the solution for any other person seeing their otherwise stable website losing their session state when hosted on a server which they do not have administrative access to.

Oh, and I found that IIS logs were pretty useless here. The best diagnosis logging here, I found, was my own manual logging to determine that this was the scenario.