具有自定义身份验证和 ClaimsIdentity 的 MVC 5 SecurityStampValidator

MVC 5 SecurityStampValidator with custom authentication and ClaimsIdentity

我有一个遗留应用程序,我正在尝试更新它以使用带 Owin 身份验证的 MVC 5。但是,我一直在尝试让 SecurityStamp 验证正常工作。我可能遗漏了拼图的一些基本部分,但我无法弄清楚它是什么。

首先我没有使用 Entity Framework。我有现有的用户 tables,我真的不想修改太多,因为它们在很多遗留代码中使用。

到目前为止我有以下...

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

我目前的计划只是让 securitystamp 验证始终通过,然后我将更改它以根据用户的最后修改时间戳创建 securitystamp table。

在调试器中,我可以看到此函数在 2 分钟后被调用,但它始终无法通过验证。当 Owin 调用这个函数来获取当前的安全戳时,它应该将它与什么进行比较?

在我的 SPUserManager class 中,我有以下函数来创建声明身份...

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# 代码示例很好。

您的用户确实缺少 SecurityStamp。尽管您的 SPUserStore class.

上有 IUserSecurityStampStore

默认 SecurityStampValidatorIUserSecurityStampStore.GetSecurityStampAsync(userId) 中为用户获取 SecurityStamp 值。并将该值与 AspNet.Identity.SecurityStamp 类型的 Claim 中存储在 cookie 中的值进行比较。如果值不匹配,您的用户将被踢出。

因此,如果您尚未对用户实施 SecurityStamp,请关闭 SecurityStampValidtor

或者确保将随机值(默认情况下为 guid)放入数据库中的 user.SecurityStamp。当您在 CreateIdentityAsync 中创建 ClaimsIdentity 时,请确保添加另一个声明:

claims.Add(New Claim(Constants.DefaultSecurityStampClaimType, user.SecurityStamp))

您可以查看 SecurityStampValidator 源代码 here 并关注那里发生的事情,以避免您的用户因错误原因被注销。