2017-02-13 22 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(接口herehere)。

实施此接口时,还必须实现所有功能接口(用于获取密码,双因素身份验证(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注册替换EF提供者注册(来源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和其他Identity类将使用您的用户/角色存储。但是它的价值更麻烦,除非你有一个现有的无法映射到EF /已知提供者的数据库结构。