【问题标题】:Timeout not working in ASP.Net MVC FormsAuthentication超时在 ASP.Net MVC FormsAuthentication 中不起作用
【发布时间】:2012-01-24 15:49:39
【问题描述】:

我正在使用 FormsAuthentication,我在设置 TimeOut 值时遇到问题。

我看过其他一些与此相关的帖子,但它们似乎不是我的问题,或者建议的解决方案没有帮助。

我的 web.config 有以下内容:

<authentication mode="Forms">
  <forms loginUrl="~/Account/LogOn"
         timeout="1"
         cookieless="UseCookies" />
</authentication>

我已在要保护的控制器上放置了 AuthorizeAttribute。

我可以查看 .ASPXAUTH cookie(使用 FireCookies),我可以看到它被设置为在登录后 1 分钟内过期。

如果我通过我的代码进行调试,我可以看到 FormsAuthentication.Timeout = 1。

但是我的票似乎没有在 1 分钟内超时。闲置 1 分钟后,我仍然可以使用 AuthorizeAttribute 浏览到控制器。

事实上,我实际上可以使用 FireCookies 删除 .ASPXAUTH cookie,并且我仍然可以使用 AuthorizeAttribute 浏览到控制器。

奇怪的是,长时间不活动后(抱歉没有确切的时间 - 我出去吃午饭了!)超时发生并且我被重定向 到登录屏幕。

有什么想法吗?

【问题讨论】:

    标签: asp.net-mvc-3


    【解决方案1】:

    我也有同样的问题。实际上,它的出现是因为我无法从 javascript 中读取表单身份验证 cookie,过了一段时间 undefined。我只是想知道我是否通过 javascript 进行了身份验证。

    后来我发现票已经过期了,但我并没有被注销(也是。所以我也想解决这个问题)!我看到你的问题没有得到回答,所以我在解决我的问题时保持开放状态半天。以下是我想出的似乎有效的方法。

    我的答案基于此答案。 https://stackoverflow.com/a/454639/511438 用户 ScottS

    这是在我的 ASP.NET MVC 3 项目中。

    这是我的登录代码。未显示,它之前的自定义用户身份验证逻辑。这只是设置初始票证。

    公共类 FormsAuthenticationService : IFormsAuthentication

    public void SignIn(string userName, bool createPersistentCookie, string role)
    {
        FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
                1,                             // version
                userName,           // user name
                DateTime.Now,                  // created
                DateTime.Now.Add(FormsAuthentication.Timeout),   // expires
                false,                    // rememberMe?
                role                        // can be used to store roles
                );
    
        string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
    
        HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
        HttpContext.Current.Response.Cookies.Add(authCookie);
    }
    

    在同一个类中,但是从 global.asax 访问的静态方法

    //-- this is based on https://stackoverflow.com/questions/454616/asp-net-cookies-authentication-and-session-timeouts
    internal static FormsAuthenticationTicket RefreshLoginCookie(bool retainCurrentExpiry)
    {
        HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
        if (authCookie == null || authCookie.Value == null)
            return null;
    
        FormsAuthenticationTicket oldTicket = FormsAuthentication.Decrypt(authCookie.Value);
    
        DateTime expiryDate = (retainCurrentExpiry ? oldTicket.Expiration : DateTime.Now.Add(FormsAuthentication.Timeout));
        HttpContext.Current.Response.Cookies.Remove(FormsAuthentication.FormsCookieName);
    
        var newTicket = new FormsAuthenticationTicket(oldTicket.Version, oldTicket.Name, oldTicket.IssueDate, expiryDate,
            oldTicket.IsPersistent, oldTicket.UserData, oldTicket.CookiePath);
    
        HttpCookie newAuthCookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(newTicket));
        HttpContext.Current.Response.Cookies.Add(newAuthCookie);
    
        return newTicket;
    
    }
    

    Global.asax

    我的自定义来自 ajax 请求不刷新表单身份验证票。因此,如果您在超时期间坐在那里,ajax 请求会将您注销。如果您希望 ajax 请求保持票证有效,请更改此设置(解决我的 javascript cookie 问题,而不是您的注销不活动问题)。 *(提示,如果您已注销,则登录,但再次返回登录页面,第一次登录可能未在查询字符串中指定 returnUrl)。 *

    protected virtual void Application_AuthenticateRequest(Object sender, EventArgs e)
    {
        HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
        if (authCookie == null || authCookie.Value == "")
        {
            return;
        }
    
        bool isAjax = new HttpRequestWrapper(System.Web.HttpContext.Current.Request).IsAjaxRequest();
    
        FormsAuthenticationTicket authTicket;
        try
        {
            //-- THIS IS WHAT YOU WANT
            authTicket = FormsAuthenticationService.RefreshLoginCookie(isAjax);
        }
        catch
        {
            return;
        }
    
        string[] roles = authTicket.UserData.Split(';');
        if (Context.User != null) Context.User = new GenericPrincipal(Context.User.Identity, roles);
    
    }
    

    Web.config 这是我设置会话超时和票证超时的部分

    <configuration>
        <system.web>
            <sessionState mode="InProc" timeout="60" />
            <authentication mode="Forms">
                <forms loginUrl="~/Account/Login" timeout="60" name="ProviderMvcSession" cookieless="UseCookies" />
            </authentication>
    

    【讨论】:

    • 我看过你的代码 RefreshLoginCookie() 这个函数用旧数据生成 auth cookie 但为什么就是不明白。在什么样的情况下人们会采用这种方法?
    【解决方案2】:

    一个明显的解决方案很容易被某些人查看,清除浏览器 cookie 或注销应该可以解决问题。如果选中记住我,则应用程序将继续使用旧 cookie 登录,而不管对 Web.Config 超时值所做的更改。

    【讨论】:

      【解决方案3】:

      这与您的会话超时时间有关。默认为 20 分钟,您可以在 web.config 中更改它,如下所示:

      <sessionState mode="InProc" timeout="20"/>
      

      【讨论】:

      • 但会话状态与 AuthenticationTicket/.ASPXAUTH cookie 是分开的。至少我认为是?!
      • 如果您不使用 cookie 来存储这些数据,则 session 负责处理它。
      • 但我正在使用cookies!我有 cookieless="UseCookies"。感谢您的回复。我对此感到非常困惑-您的建议有效,但我不知道为什么?
      猜你喜欢
      • 2010-12-12
      • 1970-01-01
      • 2016-07-11
      • 2014-12-13
      • 1970-01-01
      • 2012-06-15
      • 1970-01-01
      • 2018-07-03
      • 1970-01-01
      相关资源
      最近更新 更多