使用 ASP .Net 会员资格使用户登录持久化

发布于 2024-07-15 23:25:09 字数 3234 浏览 5 评论 0原文

我有一个用 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

I have a website that is built in ASP.NET 3.5 & SQL Server 2005, using the sql membership provider, and presumably forms authentication.

Since security needs on my site are very low, I would like to authenticate once, and then keep the log in persisted indefinitely (without giving the user the choice).

What is happening is that the user logs in, stays logged in for the session, and then the next time they arrive, they are logged out.

How can I get the log-in persisted?

Here's the technical details, I have experimented with many variations of durations.

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

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

Edit: Here is the cookie information that is getting stored by the client:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

唯憾梦倾城 2024-07-22 23:25:09

我终于解开了最后一块拼图。 当我的服务器的应用程序池被回收(由托管提供商配置)时,视图状态加密密钥会自动重新生成。 这意味着即使 cookie 有效且无效, 非过期(返回前访问),当用户返回时,加密已更改,并且 cookie 不再有效。

解决方案是手动指定静态验证密钥。 以下链接可用于为此生成必要的 web.config 标记。

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

更新:

这是一个更可配置的站点,用于生成机器密钥

源树 - Genage 属性

我意识到这可能会产生轻微的安全影响,我想理论上来说,更改密钥会更安全,以防您的密钥被暴力破解并危及您可能存储在视图状态中的任何数据,但您可能不应该在视图状态中存储敏感信息,因为它本身并不安全。

例子:

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

I finally figured out the last piece of the puzzle. When the app pool of my server was being recycled (configured by the hosting provider), the viewstate encryption key was being auto-re-generated. This meant that even though the cookies were valid & non expired (pre-return visit), when the user returned the encyrption had changed, and the cookie was no longer valid.

The solution was to manually specify a static validation key. The following link can be used to generate the neccessary web.config tag for this.

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

UPDATE:

Here's a more configurable site to generate Machine Key

Source Tree - Generage attribute

I realize that this might have a minor security impact, I guess theoritically it's safer to have a changing key in case your key gets brute forced and compromises any data you might be storing in the view state, but you probably shouldn't be storing sensitive information in the viewstate as it's not inherently safe anyway.

Example:

<configuration>
  <system.web>
    <machineKey
        validationKey="97CEB2D3DEBF853649EAB851F56F08BA328423F935C97244CF5300925B6FF7D2C43084C73CBAF19D5193755EF7F87A3FFC714675F9197C822BAEEC97E853B91E"
        decryptionKey="A72F69A4650348E3AA249A8179516D67C8553B3D4BD165B9"
        validation="SHA1" />
  </system.web>
</configuration>
霞映澄塘 2024-07-22 23:25:09

我认为您最好使用 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();

希望这会有所帮助。

I think you'd be better-off using the FormsAuthentication.SetAuthCookie method rather than writing a lot of code yourself.

I believe your membership provider settings in the web.config may be conflicting with the settings you're providing in code, plus you're not providing a cookie name.

Try the following:

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

In conjunction with the following settings in 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>

Simply change the "timeout" value in the authentication block to be a longer value if you really want to create an indefinite log-in period. I believe 432000 = 5 days.

If you want your users to be able to explicitly log-out, simply call the following method in response to a button click (or whatever):

FormsAuthentication.SignOut();

Hope this helps.

乜一 2024-07-22 23:25:09

阅读代码时,您可能不小心将 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

此处还有一篇不错的 Microsoft 知识库文章,内容为“了解表单身份验证票证和饼干”

Reading your code you might have accidently set the FormsAuthenticationTicket timeout value to zero. The line in your code where you create the ticket reads: -

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

The value of Expiration.Subtract(Expiration).TotalMinutes will always be "0".

You may be better using the longhand format for creating the ticket as follows which would result in less ambiguity.

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

There is also a good Microsoft KB article here on "Understanding the Forms Authentication Ticket and Cookie"

.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文