Идентификатор 2.0 с пользовательскими таблицами

#c# #asp.net #asp.net-mvc-5 #asp.net-identity-2

#c# #asp.net #asp.net-mvc-5 #asp.net-identity-2

Вопрос:

Я новичок в ASP.NET идентичность, и я все еще пытаюсь разобраться в том, как все это работает. К сожалению, я обнаружил, что многие из учебников, которые я пробовал, предназначены для Identity 1.0, тогда как я пытаюсь работать с Identity 2.0.

Самая большая проблема, с которой я сталкиваюсь, — это то, что, как я думал, будет простым, но оказалось, что это не так. То, что я пытаюсь сделать, это использовать существующую базу данных с существующей таблицей пользователей. В настоящее время все, что я могу сделать, это получить Identity для создания собственных таблиц для хранения пользовательских данных. Я не хочу использовать Entity Framework, но мне было очень трудно отделить Entity Framework от Identity 2.0.

В моей ситуации я использую SQL Server, я подумал, что попробую внедрить пользовательский поставщик для MySQL по этой ссылке: http://www.asp.net/identity/overview/extensibility/implementing-a-custom-mysql-aspnet-identity-storage-provider и https://github.com/raquelsa/AspNet .Идентификация.MySQL. Похоже, это работает только под идентификатором 1. Однако, похоже, существует более новая версия, которая использует Entity Framework. Я также пробовал https://github.com/ILMServices/RavenDB.AspNet .Идентификация.

Со всем, что я пробовал, я застрял в следующей строке:

 var manager = new IdentityUserManager(new UserStore<IdentityUser>(context.Get<ApplicationDbContext>()));
 

Проблема, с которой я сталкиваюсь, заключается в том, что мне нужно удалить класс ApplicaitonDbContext в соответствии с инструкциями для RavenDB, однако я не знаю, что поместить в эту строку вместо этого.

Ошибки, которые я получаю, следующие:

Нестандартный тип ‘AspNet.Идентификация.MySQL.UserStore’ не может использоваться с аргументами типа

и

Не удалось найти тип или имя пространства имен ‘ApplicationDbContext’ (вам не хватает директивы using или ссылки на сборку?)

Следует ожидать второй ошибки, однако я не уверен, что использовать в этой строке кода вместо этого. У кого-нибудь был опыт внедрения пользовательского поставщика без использования Entity Framework?

Спасибо.

Обновление 1:

Я попытался выполнить следующее руководство [ http://aspnetguru.com/customize-authentication-to-your-own-set-of-tables-in-asp-net-mvc-5 / ] но он кажется неполным, с ошибками компиляции или времени выполнения при точном следовании руководству. У меня все еще есть несколько проблем…

При замене всех экземпляров «ApplicationUser» на «User» возникает проблема со следующей строкой в IdentityConfig.cs

 var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<MyDbContext>()));
 

Изменение ApplicationUser на User приводит к следующей ошибке

Тип ‘WebApplicationTest2.Models.Пользователь’ не может использоваться в качестве параметра типа ‘TUser’ в общем типе или методе ‘Microsoft.AspNet.Идентификация.EntityFramework.Пользовательское хранилище ‘. Нет неявного преобразования ссылок из ‘WebApplicationTest2.Models.Пользователь «для» Microsoft.AspNet.Идентификация.EntityFramework.IdentityUser’.

Мне также трудно понять, как использовать диспетчер пользователей и многие асинхронные методы. Следующие строки не работают:

 AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, await user.GenerateUserIdentityAsync(UserManager));
 

В AccountController.cs со следующими ошибками:

Лучший перегруженный метод соответствует ‘Microsoft.Owin.Security.IAuthenticationManager.Вход в систему (Microsoft.Owin.Security.Свойства аутентификации, параметры системы.Безопасность.Претензии.ClaimsIdentity[])’ имеет некоторые недопустимые аргументы.

‘WebApplicationTest2.Models.User’ не содержит определения для ‘GenerateUserIdentityAsync’ и никакого метода расширения ‘GenerateUserIdentityAsync’, принимающего первый аргумент типа ‘WebApplicationTest2.Models.Пользователь’ может быть найден (вам не хватает директивы using или ссылки на сборку?)

Ответ №1:

В ваших примерах вы, кажется, хотите заменить на DbContext что-то другое, но я считаю, что на самом деле вам нужно сосредоточить свои усилия на одном уровне выше.

В фреймворке есть класс UserManager , который отвечает за управление пользователями и связанной с ними информацией, но не за ее хранение. Когда требуется сохранить пользователей (или связанную с ними информацию), по умолчанию используется предоставленный UserStore<IdentityUser> , который знает, как хранить IdentityUser экземпляры в базе данных с помощью a DbContext .

В рамках 2.0 различные биты хранения идентификаторов были разбиты на несколько интерфейсов. Предоставленная реализация по умолчанию UserStore<IdentityUser> реализует несколько из этих интерфейсов и сохраняет данные для них всех в базе данных с помощью a DBContext .

Если вы посмотрите на определение пользовательского хранилища на основе entity Framework, предоставляемого по умолчанию, вы можете увидеть, что оно реализует многие из этих небольших интерфейсов:

 public class UserStore<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim> : IUserLoginStore<TUser, TKey>, 
IUserClaimStore<TUser, TKey>, IUserRoleStore<TUser, TKey>, IUserPasswordStore<TUser, TKey>, 
IUserSecurityStampStore<TUser, TKey>, IQueryableUserStore<TUser, TKey>, IUserEmailStore<TUser, TKey>, 
IUserPhoneNumberStore<TUser, TKey>, IUserTwoFactorStore<TUser, TKey>, IUserLockoutStore<TUser, TKey>, 
IUserStore<TUser, TKey>, IDisposable 
where TUser : IdentityUser<TKey, TUserLogin, TUserRole, TUserClaim>
where TRole : IdentityRole<TKey, TUserRole>
where TKey : Object, IEquatable<TKey>
where TUserLogin : new(), IdentityUserLogin<TKey>
where TUserRole : new(), IdentityUserRole<TKey>
where TUserClaim : new(), IdentityUserClaim<TKey>
 

Поскольку вы вообще не хотите использовать Entity Framework, вам необходимо предоставить свои собственные реализации некоторых из этих ключевых интерфейсов, которые будут хранить эти данные в тех местах, где вы хотите, чтобы данные были сохранены. Основной интерфейс IUserStore<Tuser,TKey> . это определяет контракт на хранение пользователей, у которых есть ключ определенного типа. Если вы хотите хранить только пользователей и никакой другой информации, вы можете реализовать этот интерфейс, а затем передать свою реализацию в UserManager , и все должно быть готово.

Маловероятно, что этого будет достаточно, хотя, скорее всего, вам понадобятся пароли, роли, логины и т. Д. Для ваших пользователей. Если это так, то вам нужно создать свой класс, который реализует IUserStore<Tuser,TKey> IUserPasswordStore<TUser, TKey> также IRoleStore<TRole, TKey> IUserClaimStore<TUser, TKey> implementи .

Вы можете найти список всех интерфейсов в MSDN здесь

В зависимости от битов, которые вы хотите использовать, вам необходимо реализовать эти интерфейсы.

Вероятно, вам также потребуется определить свои собственные версии Identity* классов, которые существуют для Entity framework уже из коробки. Итак, вам понадобится ваш собственный IdentityUser класс, который представляет пользователей, которых вы хотите сохранить, и IdentityUserClaim для утверждений пользователей. Я сам этого не делал, поэтому не совсем уверен, но мне кажется, что вам придется это сделать.

У Скотта Аллена есть хорошая статья о различных элементах модели, которые могут быть полезны.

Что касается ваших проблем с этой строкой:

 AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, await user.GenerateUserIdentityAsync(UserManager));
 

Существует вызываемый метод GenerateUserIdentityAsync , который определяется, на Applicationuser который распространяется IdentityUser . Я полагаю, что он определен в проекте шаблона и выглядит примерно так:

 public class ApplicationUser : IdentityUser 
{    
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(
    UserManager<ApplicationUser> manager) {
    // Note the authenticationType must match the one 
    // defined in CookieAuthenticationOptions.AuthenticationType
    var userIdentity = 
        await manager.CreateIdentityAsync(this, 
            DefaultAuthenticationTypes.ApplicationCookie);
    // Add custom user claims here
    return userIdentity;
    }
}
 

Поскольку вы больше не используете entity framework IdentityUser , вам либо нужно определить аналогичный метод или свой собственный User класс, либо реализовать ту же функциональность каким-либо другим способом (например, просто вызвать await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie) вместо этого)

Комментарии:

1. Похоже, это лучший вариант, который у меня есть, и выглядит очень многообещающе, а срок действия вознаграждения истекает, поэтому я отдал его вам. Спасибо.

2. Джош, ты смог заставить это работать? Я собираюсь сделать то же самое прямо сейчас.

3. Эта статья мне очень помогла.

4. Здесь есть очень хорошая статья: jamessturtevant.com/posts/ASPNET-Identity2.0-Custom-Database

Ответ №2:

Я сам довольно новичок в Identity. Реализует ли ваша пользовательская сущность интерфейс IUser? например

 public partial class User : IUser<Guid> //Whatever your key is
{
    public Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager)
    {
        return Task.FromResult(GenerateUserIdentity(manager));
    }

    public ClaimsIdentity GenerateUserIdentity(ApplicationUserManager manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = manager.CreateIdentity<User, Guid>(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }
}
 

Затем для входа в систему вы можете вызвать вышеуказанный:

 public async Task SignInAsync(User user, bool isPersistent)
    {
        var userIdentity = await user.GenerateUserIdentityAsync(UserManager);
        AuthenticationManager.SignIn(
            new AuthenticationProperties
            {
                IsPersistent = isPersistent
            },
            userIdentity
        );
    }   
 

Ответ №3:

Я думаю, что это было недавно обновлено до этого в ApplicationUser :

 public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
{
    // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
    var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
    // Add custom user claims here
    return userIdentity;
}
 

Он вызывается следующим образом из AccountController -> GetExternalLogin

 ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,
    OAuthDefaults.AuthenticationType);
ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager,
    CookieAuthenticationDefaults.AuthenticationType);