2017-02-13 4 views
0

Возможно ли использовать стандартную аутентификацию asp net core в шаблоне универсального репозитория, и если да, то как?Использование ApplicationUser в шаблоне общего репозитория

Я могу создать проект, который использует общий шаблон репозитория для всего моего кода, за исключением стороны аутентификации проекта, которая использует метод по умолчанию.

Мой репозиторий выглядит следующим образом:

using System.Linq; 
using DemoWebsite.Interfaces; 
using Microsoft.EntityFrameworkCore; 

namespace DemoWebsite.Data 
{ 
public class Repository<T> : IRepository<T> where T : class 
{ 
    protected readonly DbContext Context; 
    protected DbSet<T> DbSet; 

    public Repository(ApplicationDbContext context) 
    { 
     Context = context; 
     DbSet = context.Set<T>(); 
    } 

    public void Add(T entity) 
    { 
     Context.Set<T>().Add(entity); 

     Save(); 
    } 

    public T Get<TKey>(TKey id) 
    { 
     return DbSet.Find(id); 
    } 

    public IQueryable<T> GetAll() 
    { 
     return DbSet; 
    } 

    public void Update(T entity) 
    { 
     Save(); 
    } 

    private void Save() 
    { 
     Context.SaveChanges(); 
    } 
} 
} 

Мой ApplicationDbContext класс:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser> 
{ 
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) 
     : base(options) 
    { 
    } 

    protected override void OnModelCreating(ModelBuilder builder) 
    { 
     base.OnModelCreating(builder); 
     // Customize the ASP.NET Identity model and override the defaults if needed. 
     // For example, you can rename the ASP.NET Identity table names and more. 
     // Add your customizations after calling base.OnModelCreating(builder); 
    } 
} 
+2

Зачем смешивать обязанности? Репозиторий должен нести ответственность за получение данных. Аутентификация не несет ответственности за репозиторий. Для этого вы должны использовать что-то вроде IAuthenticationFilter и применять его к контроллерам или действиям. Когда вы вызываете репозиторий, пользователь должен быть авторизовано для этого –

+0

. Таким образом, предпочтительный способ обработки аутентификации - оставить его как есть и просто использовать общий репозиторий для остальной части моих данных? Я просто пытался все это под одной крышей –

+1

@MarcusS: Теоретически можно было бы так сказать. Вам нужно будет реализовать свой собственный IUserStore со всеми его функциями (для получения паролей и т. Д. См. Здесь EF. Https://github.com/aspnet/Identity/blob/rel/1.1.0/src/Microsoft.AspNetCore .Identity.EntityFrameworkCore/UserStore.cs # L161-L170), а затем зарегистрируйте его самостоятельно https://github.com/aspnet/Identity/blob/rel/1.1.0/src/Microsoft.AspNetCore.Identity.EntityFrameworkCore/IdentityEntityFrameworkBuilderExtensions. CS # L45-L51. Больше проблем, чем это стоит, если у вас нет структуры БД, которая не может быть сопоставлена ​​с EF/известными поставщиками – Tseng

ответ

3

Да, это возможно, но это совсем немного усилий, чтобы сделать это. Вам необходимо будет выполнить IUserStore и, возможно, IRoleStore (интерфейсы here и here).

При реализации этих интерфейсов вам также необходимо реализовать все интерфейсы функций (для получения паролей, двухфакторной аутентификации (here), маркировки безопасности и т. Д.).

Для примера реализации вы всегда можете посмотреть источник EF Core Identity provider.

Как это

public abstract class UserStore<TUser, TRole, TContext, TKey, TUserClaim, TUserRole, TUserLogin, TUserToken, TRoleClaim> : 
    IUserLoginStore<TUser>, 
    IUserRoleStore<TUser>, 
    IUserClaimStore<TUser>, 
    IUserPasswordStore<TUser>, 
    IUserSecurityStampStore<TUser>, 
    IUserEmailStore<TUser>, 
    IUserLockoutStore<TUser>, 
    IUserPhoneNumberStore<TUser>, 
    IQueryableUserStore<TUser>, 
    IUserTwoFactorStore<TUser>, 
    IUserAuthenticationTokenStore<TUser> 
    where TUser : IdentityUser<TKey, TUserClaim, TUserRole, TUserLogin> 
    where TRole : IdentityRole<TKey, TUserRole, TRoleClaim> 
    where TContext : DbContext 
    where TKey : IEquatable<TKey> 
    where TUserClaim : IdentityUserClaim<TKey> 
    where TUserRole : IdentityUserRole<TKey> 
    where TUserLogin : IdentityUserLogin<TKey> 
    where TUserToken : IdentityUserToken<TKey> 
    where TRoleClaim : IdentityRoleClaim<TKey> 
{ 
    ... 
} 

Ваш магазин пользователя может выглядеть следующим образом:

public class GenericUserStore<TUser> : IUserStore<TUser>, 
    IUserPasswordStore<TUser> where TUser : ApplicationUser 
{ 
    public GenericUserStore(IRepository<TUser> userRepo) { } 

    public Task<TUser> FindByIdAsync(string userId, CancellationToken cancellationToken) 
    { 
     return userRepo.Get(userId); 
    } 

    ... 
} 

и та же для RoleStore. Затем, наконец, замените регистрацию EF Provider собственными (источник EF here).

userStoreType = typeof(GenericUserStore<,,,>).MakeGenericType(userType, roleType, contextType, keyType); 
roleStoreType = typeof(GenericRoleStore<,,>).MakeGenericType(roleType, contextType, keyType); 

var services = new ServiceCollection(); 
services.AddScoped(
    typeof(IUserStore<>).MakeGenericType(userType), 
    userStoreType); 
services.AddScoped(
    typeof(IRoleStore<>).MakeGenericType(roleType), 
    roleStoreType); 

Тогда UserManager и другие классы Удостоверения будут использовать User/Role магазин. Но это больше проблем, чем это стоит, если у вас нет существующей структуры БД, которая не может быть сопоставлена ​​с EF/известными провайдерами.