为什么我的表单身份验证票证到期如此之快?

时间:2010-07-03 03:26:14

标签: c# .net asp.net authentication forms-authentication

我在ASP.NET应用程序中使用表单身份验证。我将FormsAuthenticationTicket配置为在1年后到期,但实际上在1小时后到期。我无法弄清楚原因。

以下是登录过程中涉及的所有代码:

public static bool Login(int id)
{
    try
    {
        string securityToken = UserHelper.AuthenticateUser(id);

        DateTime expiryDate = DateTime.Now.AddYears(1);
        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
             1, id.ToString(), DateTime.Now, expiryDate, true,
             securityToken, FormsAuthentication.FormsCookiePath);

        string encryptedTicket = FormsAuthentication.Encrypt(ticket);
        HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
        cookie.Expires = expiryDate;

        HttpContext.Current.Response.Cookies.Add(cookie);

        return true;
    }
    catch
    {
        return false;
    }
}

的Web.config:

<system.web>
    <machineKey validationKey="AutoGenerate"
    decryptionKey="AutoGenerate" validation="SHA1" />
    <compilation debug="true">
    <authentication mode="Forms">
        <forms loginUrl="~/Login.aspx" timeout="2880"/>
    </authentication>
...

我的做法有问题吗?为什么到期这么快?

修改

Global.asax代码:

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    if (Request.PhysicalPath.EndsWith(".aspx") || Request.PhysicalPath.EndsWith(".axd") || Request.PhysicalPath.EndsWith(".ashx"))
        SecurityManager.SetPrincipal();
}

SetPrincipal Code:

public static void SetPrincipal()
{
    ILivrePrincipal principal = null;
    FormsIdentity identity;
    UrlParameters urlParameters = UrlParametersHelper.GetUrlParameters(HttpContext.Current.Request);

    if (HttpContext.Current.Request.IsAuthenticated)
    {
        identity = (FormsIdentity)HttpContext.Current.User.Identity;

        User userProfile;
        urlParameters.SecurityToken = (((FormsIdentity)identity).Ticket).UserData;
        try
        {
            userProfile = UserHelper.GetUser(urlParameters.SecurityToken);
            UserHelper.UpdateLastActiveOn(userProfile);
            principal = new AuthenticatedPrincipal(identity, userProfile);
        }
        catch
        {
            //TODO: Log an exception
            FormsAuthentication.SignOut();
            principal = new AnonymousPrincipal(new GuestIdentity(), UserHelper.GetUser(null));
        }
    }
    else
    {
        principal = new AnonymousPrincipal(new GuestIdentity(), UserHelper.GetUser(null));
    }

    HttpContext.Current.User = principal;
}

5 个答案:

答案 0 :(得分:7)

这是你的问题。

<machineKey validationKey="AutoGenerate" 
            decryptionKey="AutoGenerate" 
            validation="SHA1"/>

每次应用程序池回收时,ASP都会生成一个新的机器密钥。每小时都可能发生这种情况。

计算机密钥用于加密和解密FormsAuthentication cookie。如果它发生变化,浏览器上的cookie就不再有用了。因此,系统会将您视为您从未登录过。

尝试生成静态密钥并将其添加到配置文件中。应该看起来像这样:

<machineKey  
    validationKey="21F090935F6E49C2C797F69(snip)F1B72A7F0A281B"          
    decryptionKey="ABAA84D7EC4BB56D75D(snip)B8BF91CFCD64568A145BE59719F"
    validation="SHA1"
    decryption="AES"
/>

为自己生成一个密钥here

答案 1 :(得分:1)

我没有看到代码有任何问题。您使用的是什么浏览器,或许它不能识别1年的到期日期?我会用fiddler或一些这样的工具查看响应头文件,看看实际发送的是什么。

答案 2 :(得分:1)

这可能会有助http://support.microsoft.com/kb/910439/

我的猜测是该cookie在票证到期之前到期。上面的文章向您展示了调试的方法,以确定是否确实如此。

答案 3 :(得分:0)

我唯一能看到的是非标准的是你将id.ToString()传递给FormsAuthenticationTicket构造函数。我通常在这个参数中传递用户名。不确定这是否会有所作为,但值得一试。

答案 4 :(得分:0)

您是否在应用程序中使用可能导致超时的任何其他内容? 例如,如果进程内会话状态到期,则自动将您注销。

我假设您在Global.asax中有一些代码来处理经过身份验证的请求吗?