MVC 5 SecurityStampValidator с настраиваемой аутентификацией и ClaimsIdentity

У меня есть устаревшее приложение, которое я пытаюсь обновить, чтобы использовать MVC 5 с аутентификацией Owin. Однако я застрял, пытаясь заставить проверку SecurityStamp работать правильно. Я, вероятно, упускаю какую-то фундаментальную часть головоломки, но я не могу понять, что это такое.

Во-первых, я не использую Entity Framework. У меня есть существующие пользовательские таблицы, которые я не хочу слишком сильно изменять, поскольку они используются во многих устаревших кодах.

Пока у меня есть следующее ...

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 Identity, и впервые использовал MVC. Любая помощь будет принята с благодарностью. Я могу включить любой другой код, который может быть уместен.

Мои извинения за VB.Net. Кажется, что никто не использует VB.Net для такого рода вещей, но я как бы застрял с ним, так как существует слишком много существующего устаревшего кода для преобразования. Примеры кода C # в порядке.


person user1751825    schedule 27.09.2015    source источник


Ответы (1)


Вам действительно не хватает SecurityStamp на вашем пользователе. Хотя у вас IUserSecurityStampStore в вашем SPUserStore классе.

По умолчанию SecurityStampValidator принимает значение SecurityStamp для пользователя из IUserSecurityStampStore.GetSecurityStampAsync(userId). И сравните значение со значением, хранящимся в файле cookie в заявлении типа AspNet.Identity.SecurityStamp. И если значения не совпадают, вашего пользователя выгоняют.

Поэтому, если у вас еще не реализовано SecurityStamp для пользователя, выключите SecurityStampValidtor.

Или убедитесь, что вы поместили случайное значение (по умолчанию это guid) в user.SecurityStamp в вашей базе данных. И когда вы создаете ClaimsIdentity в CreateIdentityAsync, убедитесь, что вы добавили еще одно утверждение:

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

Вы можете посмотреть SecurityStampValidator исходный код здесь и просто следите за тем, что там происходит, чтобы ваш пользователь не вышел из системы по неправильной причине.

person trailmax    schedule 27.09.2015
comment
Спасибо @trailmax, я добавил претензию, и теперь она работает. - person user1751825; 28.09.2015