#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);