我的ASP.NET Identity提供程序有问题。我从Visual Studio 2019附带的默认模板开始,目标是.NET 4.7.2 WebForms。
在更改密码页面上,Identity提供程序似乎没有更新.AspNet.ApplicationCookie
以反映新的SecurityStamp
。我可以在Fiddler中看到,ASP.NET正在发送一个302重定向回Manage.aspx页面,并发送一个auth cookie,该cookie大概应该反映密码更改后产生的新SecurityStamp
,但它没有。因此,在密码或2FA更改后,用户会立即从应用程序中注销,因为我将validateInterval
设置为TimeSpan.Zero
。如果我将其设置为另一个值,则无论cookie的实际年龄如何,用户的cookie在该值之后都将无效。
app.UseCookieAuthentication(New CookieAuthenticationOptions() With {
.AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
.ExpireTimeSpan = TimeSpan.FromDays(14),
.SlidingExpiration = True,
.Provider = New CookieAuthenticationProvider() With {
.OnValidateIdentity = SecurityStampValidator.OnValidateIdentity(Of ApplicationUserManager, ApplicationUser)(
validateInterval:=TimeSpan.Zero,
regenerateIdentity:=Function(manager, user) user.GenerateUserIdentityAsync(manager))},
.LoginPath = New PathString("/Account/Login")})
这是更改密码页面中的相关代码:
Protected Sub ChangePassword_Click(sender As Object, e As EventArgs)
If IsValid Then
Dim manager = Context.GetOwinContext().GetUserManager(Of ApplicationUserManager)()
Dim signInManager = Context.GetOwinContext().Get(Of ApplicationSignInManager)()
Dim result As IdentityResult = manager.ChangePassword(User.Identity.GetUserId(), CurrentPassword.Text, NewPassword.Text)
If result.Succeeded Then
Dim userInfo = manager.FindById(User.Identity.GetUserId())
signInManager.SignIn(userInfo, isPersistent:=False, rememberBrowser:=False)
Response.Redirect("~/Profile/Manage?m=ChangePwdSuccess")
Else
AddErrors(result)
End If
End If
End Sub
事实证明,您需要注销用户,然后将其重新登录:
Protected Sub ChangePassword_Click(sender As Object, e As EventArgs)
If IsValid Then
Dim userManager = Context.GetOwinContext().GetUserManager(Of ApplicationUserManager)()
Dim signInManager = Context.GetOwinContext().Get(Of ApplicationSignInManager)()
Dim authenticateResult = Context.GetOwinContext().Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie).GetAwaiter.GetResult()
Dim accountChangeResult As IdentityResult = userManager.ChangePassword(User.Identity.GetUserId(), CurrentPassword.Text, NewPassword.Text)
If accountChangeResult.Succeeded Then
Context.GetOwinContext().Authentication.SignOut(DefaultAuthenticationTypes.ApplicationCookie)
Dim userInfo = userManager.FindById(User.Identity.GetUserId())
signInManager.SignIn(userInfo, isPersistent:=authenticateResult.Properties.IsPersistent, rememberBrowser:=False)
Response.Redirect("~/Profile/Manage?m=ChangePwdSuccess")
Else
AddErrors(accountChangeResult)
End If
End If
End Sub