我有一个遗留应用程序我尝试更新以使用带有Owin身份验证的MVC 5。但是,我一直试图让SecurityStamp验证正常工作。我可能错过了一些基本的谜题,但我无法弄清楚它是什么。
首先,我没有使用实体框架。我有现有的用户表,我不太想修改它们,因为它们在很多遗留代码中被使用。
到目前为止,我有以下内容......
Public Class SPUser
Implements IUser(Of String)
...
Public Class SPUserStore
Implements IUserStore(Of SPUser)
Implements IUserPasswordStore(Of SPUser)
Implements IUserRoleStore(Of SPUser)
Implements IUserSecurityStampStore(Of SPUser)
...
Public Class SPUserManager
Inherits UserManager(Of SPUser)
...
在我的Owin启动代码中,我有以下内容......
app.UseCookieAuthentication(New CookieAuthenticationOptions() With {
.AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
.LoginPath = New PathString(url.Action("login", "auth")),
.ExpireTimeSpan = TimeSpan.FromMinutes(10),
.SlidingExpiration = True,
.Provider = New CookieAuthenticationProvider() With {
.OnValidateIdentity = SecurityStampValidator.OnValidateIdentity(
validateInterval:=TimeSpan.FromMinutes(2),
regenerateIdentityCallback:=Function(manager As SPUserManager, user As SPUser)
Return manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie)
End Function,
getUserIdCallback:=Function(claimsIdentity)
Return claimsIdentity.FindFirstValue(ClaimTypes.Sid).ToString
End Function)
}
我的用户身份验证工作正常,我的身份验证控制器可以登录用户等。但是,如果我遇到问题,请在validateInterval(目前为2分钟)之后自动启动用户。
我知道它需要检查SecurityStamp。在我的SPUserStore中,我实现了以下方法......
Public Function GetSecurityStampAsync(user As SPUser) As Task(Of String) Implements IUserSecurityStampStore(Of SPUser, String).GetSecurityStampAsync
Return Task.Run(Function()
Return user.Id
End Function)
End Function
目前我的计划只是让安全标记验证始终通过,然后我将更改它以从用户表的上次修改时间戳创建安全标记。
在调试器中,我可以看到在2分钟后调用此函数,但它始终无法通过验证。当Owin调用此函数来获取当前的安全性标记时,它应该与它进行比较?
在我的SPUserManager类中,我有以下函数来创建声明标识...
Public Overrides Function CreateIdentityAsync(user As SPUser, authenticationType As String) As Task(Of ClaimsIdentity)
Return Task.Run(Function()
Dim claims As New List(Of Claim)
claims.Add(New Claim(ClaimTypes.Sid, user.Id.ToString))
claims.Add(New Claim(ClaimTypes.NameIdentifier, user.UserName))
claims.Add(New Claim(ClaimTypes.GivenName, user.FirstName))
claims.Add(New Claim(ClaimTypes.Surname, user.LastName))
Dim identity As New ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie)
Return identity
End Function)
End Function
没有任何关于设置初始安全标记的内容,我猜应该有,但我不知道该怎么做。在IUser或ClaimsIdentity上似乎没有任何相关属性。
我真的不知道我在做什么,因为这是我第一次尝试实施基于Asp.net身份的身份验证,这是我第一次使用MVC。任何帮助将不胜感激。我可以包含其他可能相关的代码。
我对VB.Net表示歉意。似乎没有人使用VB.Net来做这种事情,但我有点坚持使用它,因为现有的遗留代码太多了。 C#代码样本很好。
答案 0 :(得分:4)
您确实错过了用户的SecurityStamp
。虽然您的IUserSecurityStampStore
课程有SPUserStore
。
默认SecurityStampValidator
从SecurityStamp
获取用户的IUserSecurityStampStore.GetSecurityStampAsync(userId)
值。并将该值与类型为AspNet.Identity.SecurityStamp
的声明中存储在Cookie中的值进行比较。如果值不匹配,您的用户就会被赶出去。
因此,如果您尚未在用户上实施SecurityStamp
,请关闭SecurityStampValidtor
。
或者确保将随机值(默认为guid)放入数据库中的user.SecurityStamp
。当您在ClaimsIdentity
中创建CreateIdentityAsync
时,请确保添加其他声明:
claims.Add(New Claim(Constants.DefaultSecurityStampClaimType, user.SecurityStamp))
您可以查看SecurityStampValidator
源代码here,然后关注那里发生的事情,以避免您的用户因错误的原因退出。