MVC 5 IoC и аутентификация
Я собираюсь начать проект, где буду использовать MVC5. Но поскольку я хочу использовать IoC, а затем повторно использовать мои пользовательские таблицы и добавлять в него настраиваемые материалы, мне очень сложно понять, как я могу использовать новую инфраструктуру Identity, которая поставляется с MVC5.
Я все больше и больше смотрю на основные формы auth. Каковы ваши решения?
Мои потребности:
- Пользовательский репозиторий/служба должна быть введена
- Пользовательский репозиторий должен находиться в DAL
- Пользовательский репозиторий должен поддерживать другие технологии, чем EF
- Аутентификация с OpenID и OAuth должна быть несколько простой в реализации
- ДОЛЖНО БЫТЬ БЕЗОПАСНО
- Должен быть повторно использован в других проектах, например. WPF
Я долго искал ответ, но все, что я вижу, жестко закодировано в контроллере.
Как вы решаете это? Вы пишете больше всего с нуля или можете привязать к чему-то, что будет масштабироваться для других платформ .NET как WCF и WPF?
Нижеприведенный код берется непосредственно из AccountController в шаблоне ASP.NET MVC 5 по умолчанию.
Первое, что он делает, это Bastard Injection
.
[Authorize]
public class AccountController : Controller
{
public AccountController()
: this(
new UserManager<ApplicationUser>(
new UserStore<ApplicationUser>(
new ApplicationDbContext())))
{
}
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
}
Принятый ответ будет передан человеку, который показывает мне, что они сделали, который включает в себя вышеуказанные требования
Ответы
Ответ 1
В итоге я решил реализовать IUserStore, IUserStore, IUserPasswordStore, IUserLoginStore, чтобы иметь возможность перемещать UserRepository в это законное место, уровень DataAccess. Но все равно получите Бенифиты безопасности Owin и новую Identity Framework.
Это довольно легко реализовать, и не нужно много абстрагировать его. Вот вкус UserStoreWrapper
namespace qubis.booking.WebApp.App_Code.Identity
{
public class UserServiceWrapper : IUserStore<ApplicationUserWrapper>,
IUserPasswordStore<ApplicationUserWrapper>,
IUserLoginStore<ApplicationUserWrapper>
{
public IUserRepository UserRepos { get; set; } // My own Interface.
public UserServiceWrapper(IUserRepository userRepo)
{
UserRepos = userRepo;
}
public async Task CreateAsync(ApplicationUserWrapper user)
{
UserRepos.Insert(user.RealUser);
}
public async Task<ApplicationUserWrapper> FindByIdAsync(string userId)
{
var appUser = UserRepos.FindByUserName(userId);
ApplicationUserWrapper wrappedUser;
if (appUser != null)
{
wrappedUser = new ApplicationUserWrapper(appUser);
}
else
wrappedUser = null;
return wrappedUser;
}
В контроллере учетной записи я просто попрошу его ввести:
public AccountController(UserManager<ApplicationUserWrapper> userManager)
{
UserManager = userManager;{ AllowOnlyAlphanumericUserNames = false };
}
И поскольку я использую Ninject, я просто устанавливаю его в ядре следующим образом:
// <summary>
// Load your modules or register your services here!
// </summary>
// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUserStore<ApplicationUserWrapper>>().To<UserServiceWrapper>();
kernel.Bind<UserManager<ApplicationUserWrapper>>().ToSelf();
}
Чтобы увидеть структуру фреймворков Identity, см. эту статью. http://www.asp.net/identity/overview/extensibility/implementing-a-custom-mysql-aspnet-identity-storage-provider
Ответ 2
Так как это .NET, стандартным подходом к безопасности является проверка подлинности на границе приложения и преобразование информации аутентификации в IPrincipal. MVC поддерживает это из коробки.
Если вам нужна другая информация, полученная во время проверки подлинности, вы можете собрать ее в Root Composition и использовать ее для составления ваших сервисов.
В качестве примера предположим, что вам нужен аутентифицированный адрес электронной почты пользователя на нижнем уровне. Любой класс, который требует адрес электронной почты пользователя, может просто запросить его как Concrete Dependency:
public class EmailThingy
{
private readonly string userEmail;
public EmailThingy(string userEmail)
{
if (userEmail == null)
throw new ArgumentNullException("userEmail");
this.userEmail = userEmail;
}
// other members go here...
}
В ASP.NET MVC корнем композиции является IControllerFactory. IIRC, вы можете вытащить данные аутентификации из метода CreateController и использовать его для составления графика объекта.
В наши дни я использую IPrincipal одинаково: я добавляю его как зависимость, вместо того, чтобы полагаться на контекст контекста Thread.CurrentPrincipal Ambient, потому что проще unit test, когда все последовательно вводится через Инъекция конструктора.
Ответ 3
Вам может быть интересно посмотреть Thinktecture.IdentityServer.v2
https://github.com/thinktecture/Thinktecture.IdentityServer.v2. Многие из ваших проблем уже реализованы и инкапсулированы. Если вы не найдете то, что вам нужно, вам придется подумать о том, как абстрагировать все эти проблемы и реализовать их самостоятельно.
Ответ 4
Если вам нужно только добавить пользовательскую реализацию UserStore эта статья может вам помочь
В основном вам нужно вводить это (зависит, хотите ли вы использовать роли, требования и т.д.):
-
Напишите класс пользователя, который реализует интерфейс IUser
public class IdentityUser : IUser {
public IdentityUser(){...}
public IdentityUser(string userName) (){...}
public string Id { get; set; }
public string UserName { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
}
-
Напишите класс хранилища пользователей, который реализует IUserStore, IUserClaimStore, IUserLoginStore, IUserRoleStore и IUserPasswordStore
public class UserStore : IUserStore<IdentityUser>,
IUserClaimStore<IdentityUser>,
IUserLoginStore<IdentityUser>,
IUserRoleStore<IdentityUser>,
IUserPasswordStore<IdentityUser> {
public UserStore(){...}
public Task CreateAsync(IdentityUser user){...}
public Task<IdentityUser> FindByIdAsync(string userId){...}
.. .
}