使用ASP .Net Membership使用户登录保持持久化

19

我有一个网站,它是用ASP.NET 3.5和SQL Server 2005构建的,使用了SQL成员资格提供程序,以及可能是表单身份验证。

由于我的网站安全需求非常低,因此我希望只需要认证一次,然后将登录信息持久保存(不给用户选择的机会)。

现在的情况是,用户登录后,在本次会话期间保持登录状态,但下次访问时,就被注销了。

我该如何实现持久化登录?

下面是技术细节,我已经尝试了许多不同时间长度的变化。

 Try
            If Membership.ValidateUser(UserName.Text, Password.Text) Then
                Security.UserManager.AuthenticateUser(UserName.Text)

                If FormsAuthentication.GetRedirectUrl(UserName.Text, False) = "/default.aspx" Then
                    Try
                        'Custom Logic'
                    Catch Ex As Exception
                        'Custom Error handling'
                    End Try
                Else
                    FormsAuthentication.RedirectFromLoginPage(UserName.Text, True)
                End If
            End If
        Catch ex As Exception
            RaiseEvent ExceptionThrown(New ApplicationException("An error occurred trying to log the user in after account creation.", ex))
        End Try

Public Shared Sub AuthenticateUser(ByVal Username As String)
    Dim Expiration As DateTime = DateTime.Now.AddMonths(3)

    Dim authTicket As FormsAuthenticationTicket = New FormsAuthenticationTicket(Username, True, Expiration.Subtract(Expiration).TotalMinutes)
    Dim EncryptedTicket As String = FormsAuthentication.Encrypt(authTicket)
    Dim AuthCookie As New HttpCookie(FormsAuthentication.FormsCookieName, EncryptedTicket)
    AuthCookie.Expires = Expiration
    HttpContext.Current.Response.Cookies.Add(AuthCookie)
End Sub

Web配置文件:

<membership defaultProvider="SqlProvider" userIsOnlineTimeWindow="15">
   <providers>
      <clear />
      <add
         name="SqlProvider"
         type="System.Web.Security.SqlMembershipProvider"
         connectionStringName="GlobalConnString"
         applicationName="/"
         enablePasswordRetrieval="false"
         enablePasswordReset="true"
         requiresQuestionAndAnswer="false"
         requiresUniqueEmail="true"
         passwordFormat="Hashed"
         minRequiredPasswordLength="5"
         minRequiredNonalphanumericCharacters="0"
      />
   </providers>
</membership>


<authentication mode="Forms">
    <forms timeout="1439200" name="SITENAME" loginUrl="/login.aspx" />
</authentication>

编辑:以下是客户端存储的cookie信息:

Name    ASP.NET_SessionId
Value   r4dz1555f1pdne45n1zrlkmg
Host    SITEADDRESS.com
Path    /
Secure  No
Expires At End Of Session

Name    .ASPXAUTH
Value   648767AC72A60DBA49650A361A2FA446BA992F792055EF5B488CADC95DF495315C1C577F1C8E67E67BD937A7AB6CC5DAED85D8D64E4ED7867FC0FC395F48FED7FB631033CE441DE85223E8B3EBAE616C
Host    www.SITEADDRESS.com
Path    /
Secure  No
Expires Tue, 09 Jun 2009 17:51:31 GMT

Name    ASP.NET_SessionId
Value   gn5pcymhfsnua455yp45wpej
Host    www.SITEADDRESS.com
Path    /
Secure  No
Expires At End Of Session

Name    SITENAME
Value   9610E8515F3DBC088DAC286E1F44311A20CB2BBB57C97F906F49BC878A6C6AC0B9011777402AEA130DCDC521EF4FBB3393DB310083F72EB502AE971183306C24F07F696B3695C67DD73166F1653DF52B
Host    www.SITEADDRESS.com
Path    /
Secure  No
Expires Tue, 20 Dec 2011 06:14:10 GMT
3个回答

22

我最终找出了难题的最后一块。当我的服务器应用程序池进行回收时(由托管提供商配置),视图状态加密密钥将被自动重新生成。这意味着即使 cookie 有效且未过期(预返回访问),当用户返回时,加密已更改,cookie 将不再有效。

解决方法是手动指定一个静态验证密钥。可以使用以下链接生成必要的 web.config 标记。

http://www.aspnetresources.com/tools/keycreator.aspx

更新:

下面这个网站可以生成更多可配置的机器密钥:

Source Tree - Generage attribute

我意识到这可能会对安全造成轻微影响。理论上来说,在情况下,密钥被暴力破解并且泄露了您在视图状态中存储的任何数据时,具有更改的密钥更安全,但实际上,在视图状态中存储敏感信息本身就不太安全。

示例:

<configuration>
  <system.web>
    <machineKey
        validationKey="97CEB2D3DEBF853649EAB851F56F08BA328423F935C97244CF5300925B6FF7D2C43084C73CBAF19D5193755EF7F87A3FFC714675F9197C822BAEEC97E853B91E"
        decryptionKey="A72F69A4650348E3AA249A8179516D67C8553B3D4BD165B9"
        validation="SHA1" />
  </system.web>
</configuration>

5
请注意,两个链接现在都已失效。 - Simon Mourier
https://www.allkeysgenerator.com/Random/ASP-Net-MachineKey-Generator.aspx 可用。 - Steve

19

我认为你最好使用FormsAuthentication.SetAuthCookie方法,而不是自己编写很多代码。

我认为您在web.config中的成员资格提供程序设置可能与您在代码中提供的设置冲突,另外您没有提供cookie名称。

请尝试以下操作:

if (Membership.ValidateUser(userName, password))
{
    FormsAuthentication.SetAuthCookie(userName, true); //Creates a cookie named "XXXAuth" - see settings in web.config below
}

与web.config中的以下设置相结合:

<authentication mode="Forms">
    <forms cookieless="UseCookies" loginUrl="~/SignIn.aspx" name="XXXAuth" slidingExpiration="true" timeout="432000"/>
</authentication>


<membership defaultProvider="XXXMembershipProvider">
    <providers>
        <clear />
        <add name="XXXMembershipProvider" type="System.Web.Security.SqlMembershipProvider" applicationName="XXX" connectionStringName="XXX" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="true" minRequiredPasswordLength="5" minRequiredNonalphanumericCharacters="0" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" passwordAttemptWindow="10" passwordStrengthRegularExpression=""/>
    </providers>
</membership>

如果您想创建无限期的登录时间,请在验证块中将“超时”值更改为更长的值。 我相信432000 = 5天。

如果您希望用户能够明确注销,请在响应按钮单击(或其他操作)时调用以下方法:

FormsAuthentication.SignOut();
希望这可以帮到你。

1
+1 提到超时值 - 我也花了一些时间才找到它,尽管我认为你应该调用:FormsAuthentication.SetAuthCookie(userName, true); 来设置 cookie。 - Zhaph - Ben Duguid
1
我已经实现了这个,可悲的是它并没有解决我的问题。看起来它既没有好的影响也没有坏的影响。 - Tom Halladay
顺便提一下,为什么他们把选项称为“TimeOut”,而不是应该称为“Expiration”? - Eduardo Molteni
2
timeout 值以分钟为单位计算。因此,432000 = 300 天。 - Michael Berdyshev

2

在阅读您的代码时,您可能意外地将FormsAuthenticationTicket超时值设置为零。您创建票证的代码行如下:

Dim authTicket As FormsAuthenticationTicket = New FormsAuthenticationTicket(Username, True, Expiration.Subtract(Expiration).TotalMinutes)

Expiration.Subtract(Expiration).TotalMinutes的值始终为“0”。

您可以使用以下长格式创建票证,这将导致更少的歧义。

Public Shared Sub AuthenticateUser(ByVal Username As String)
    Dim Expiration As DateTime = DateTime.Now.AddMonths(3)
    Dim userData As String = String.Empty

    Dim authTicket As FormsAuthenticationTicket = _
       New FormsAuthenticationTicket( _
         Username, _
         DateTime.Now, _
         Expiration, _
         true, _
         userData, _
         FormsAuthentication.FormsCookiePath)
    Dim EncryptedTicket As String = FormsAuthentication.Encrypt(authTicket)
    Dim AuthCookie As New HttpCookie(FormsAuthentication.FormsCookieName, EncryptedTicket)
    AuthCookie.Expires = Expiration
    HttpContext.Current.Response.Cookies.Add(AuthCookie)
End Sub

这里还有一篇关于“理解表单身份验证票据和Cookie”的微软KB文章(链接)

.


@OtisAardvark 很好,我本来要修复它,直到看到theDorko的答案,如果他的方法不行,我会尝试你的下一个方法。@theDorko 我之前尝试过那种方法,但我认为我的webconfig设置有误。我已经按照你的更改进行了修改,如果可以的话,我会回报的。谢谢! - Tom Halladay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接