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){...}   
        .. .
    }