• 还在为身份验证引入的Microsoft.AspNet.Identity.EntityFramework导致多上下文,生成的DB改名困扰吗?


      最近一个项目需要在API里面集成身份验证,所以选择了Microsoft.AspNet.Identity.Core,以及Microsoft.AspNet.Identity.Owin来实现,但是在实现过程中发现了需要引入Microsoft.AspNet.Identity.EntityFramework ,导致在代码内出现了多个EF的上下文,虽然网上到处有改名的方式,但是对于强迫症患者,一个工程里多个上下文始终不能接受。果断查看有无方案解决

      通过获取源码发现,Microsoft.AspNet.Identity.EntityFramework只是封装了EF,完全可以自己来做,下面简单说明下实现思路。

      本文是基于web api5.2+unity+ef来实现

      1.通过源码可以查看的继承体系

      

      可以看到其核心是Core中的UserManager来操作,并且Microsoft.AspNet.Identity.EntityFramework封装了EF的上下文和操作的模型。

      2.按照需要自定义模型

      Microsoft.AspNet.Identity.EntityFramework   IdentityRole  -> RoleInfo :IRole   只需要继承IRole即可,默认的左联按需取舍

      IdentityUser  -> UserInfo : IUser

      自定义 UserRoleInfo,UserClaimInfo,AccountLoginInfo

      3.把新的模型添加到自己的EF上下文

      通过codefirst在Map里自定义表名字段类型等,想怎么做怎么做。

      4.添加身份操作的Store替换Microsoft.AspNet.Identity.EntityFramework里的UserStore和RoleStore

      定义一个新的接口,方便注入

      

    /// <summary>
        /// 身份验证Store接口
        /// </summary>
        public interface ICustomerIdentityStore :
            IUserLoginStore<UserInfo, string>,
            IUserClaimStore<UserInfo, string>,
            IUserRoleStore<UserInfo, string>,
            IUserPasswordStore<UserInfo, string>,
            IUserSecurityStampStore<UserInfo, string>,
            IQueryableUserStore<UserInfo, string>,
            IUserEmailStore<UserInfo, string>,
            IUserPhoneNumberStore<UserInfo, string>,
            IUserTwoFactorStore<UserInfo, string>,
            IUserLockoutStore<UserInfo, string>,
            IUserStore<UserInfo>
        {
        }

      然后实现其接口,思路的通过注入把上下文的仓储注入到实现里即可对DB进行操作

      5. 自定义身份验证仓储接口和实现(样例代码)

      

    /// <summary>
        /// 身份验证仓储
        /// </summary>
        public interface IAuthRepository
        {
            /// <summary>
            /// 注册用户
            /// </summary>
            /// <param name="userModel"></param>
            /// <returns></returns>
            Task<IdentityResult> RegisterUser(UserModel userModel);
    
            /// <summary>
            /// 查找用户
            /// </summary>
            /// <param name="userName"></param>
            /// <param name="password"></param>
            /// <returns></returns>
            Task<UserInfo> FindUser(string userName, string password);
    
            /// <summary>
            /// 查找AppClient信息
            /// </summary>
            /// <param name="clientId"></param>
            /// <returns></returns>
            AppClientInfo FindClient(string clientId);
    
            /// <summary>
            /// 添加Token信息
            /// </summary>
            /// <param name="token"></param>
            /// <returns></returns>
            Task<bool> AddRefreshToken(RefreshTokenInfo token);
    
            /// <summary>
            /// 移除token信息
            /// </summary>
            /// <param name="refreshTokenId"></param>
            /// <returns></returns>
            Task<bool> RemoveRefreshToken(string refreshTokenId);
    
            /// <summary>
            /// 移除token信息
            /// </summary>
            /// <param name="refreshToken"></param>
            /// <returns></returns>
            Task<bool> RemoveRefreshToken(RefreshTokenInfo refreshToken);
    
            /// <summary>
            /// 查找token信息
            /// </summary>
            /// <param name="refreshTokenId"></param>
            /// <returns></returns>
            Task<RefreshTokenInfo> FindRefreshToken(string refreshTokenId);
    
            /// <summary>
            /// 查找所有刷新token信息
            /// </summary>
            /// <returns></returns>
            List<RefreshTokenInfo> GetAllRefreshTokens();
    
            /// <summary>
            /// 通过登录信息查找用户信息
            /// </summary>
            /// <param name="loginInfo"></param>
            /// <returns></returns>
            Task<UserInfo> FindAsync(UserLoginInfo loginInfo);
    
            /// <summary>
            /// 创建用户信息
            /// </summary>
            /// <param name="user"></param>
            /// <returns></returns>
            Task<IdentityResult> CreateAsync(UserInfo user);
    
            /// <summary>
            /// 添加用户登录信息
            /// </summary>
            /// <param name="userId"></param>
            /// <param name="login"></param>
            /// <returns></returns>
            Task<IdentityResult> AddLoginAsync(string userId, UserLoginInfo login);
        }

      然后添加其实现

      

    /// <summary>
        /// 身份验证仓储
        /// </summary>
        public class AuthRepository : IAuthRepository
        {
            /// <summary>
            /// 仓储接口
            /// </summary>
            private readonly IUnitRepository _repository;
    
            /// <summary>
            /// 工作单元
            /// </summary>
            private readonly IUnitOfWork _unitOfWork;
    
            /// <summary>
            /// 用户管理
            /// </summary>
            private readonly UserManager<UserInfo> _userManager;
    
            /// <summary>
            /// ctor
            /// </summary>
            /// <param name="repository"></param>
            /// <param name="unitOfWork"></param>
            /// <param name="userStore"></param>
            public AuthRepository(IUnitRepository repository, IUnitOfWork unitOfWork, ITaurusIdentityStore userStore)
            {
                _repository = repository;
                _unitOfWork = unitOfWork;
                _userManager = new UserManager<UserInfo>(userStore);
            }
    
    
            public async Task<IdentityResult> AddLoginAsync(string userId, UserLoginInfo login)
            {
                var result = await _userManager.AddLoginAsync(userId, login);
    
                return result;
            }
    
            public async Task<bool> AddRefreshToken(RefreshTokenInfo token)
            {
                var existingToken = _repository.FirstOrDefault<RefreshTokenInfo>(r => r.Subject == token.Subject
                && r.AppClientId == token.AppClientId);
    
                if (existingToken != null)
                {
                    var result = await RemoveRefreshToken(existingToken);
                }
    
                _repository.Insert(token);
    
                return _unitOfWork.SaveChanges() > 0;
            }
    
            public async Task<IdentityResult> CreateAsync(UserInfo user)
            {
                var result = await _userManager.CreateAsync(user);
    
                return result;
            }
    
            public async Task<UserInfo> FindAsync(UserLoginInfo loginInfo)
            {
                var user = await _userManager.FindAsync(loginInfo);
    
                return user;
            }
    
            public AppClientInfo FindClient(string clientId)
            {
                var client = _repository.FirstOrDefault<AppClientInfo>(s => s.Id == clientId);
    
                return client;
            }
    
            public Task<RefreshTokenInfo> FindRefreshToken(string refreshTokenId)
            {
                var refreshToken = _repository.FirstOrDefault<RefreshTokenInfo>(s => s.TokenId == refreshTokenId);
    
                return Task.FromResult(refreshToken);
            }
    
            public async Task<UserInfo> FindUser(string userName, string password)
            {
                var user = await _userManager.FindAsync(userName, password);
    
                return user;
            }
    
            public List<RefreshTokenInfo> GetAllRefreshTokens()
            {
                return _repository.All<RefreshTokenInfo>().ToList();
            }
    
            public async Task<IdentityResult> RegisterUser(UserModel userModel)
            {
                var user = new UserInfo
                {
                    UserName = userModel.UserName,
                    Id = Guid.NewGuid().ToString(),
                    FullName = "test",
                    CreateTime = DateTime.Now,
                    CreateBy = Guid.Empty.ToString(),
                    UpdateBy = Guid.Empty.ToString(),
                    UpdateTime = DateTime.Now
                };
    
                var result = await _userManager.CreateAsync(user, userModel.Password);
    
                return result;
            }
    
            public Task<bool> RemoveRefreshToken(RefreshTokenInfo refreshToken)
            {
                _repository.DeleteItem(refreshToken);
    
                var result = _unitOfWork.SaveChanges() > 0;
                return Task.FromResult(result);
            }
    
            public Task<bool> RemoveRefreshToken(string refreshTokenId)
            {
                var refreshToken = _repository.FirstOrDefault<RefreshTokenInfo>(s => s.Id == refreshTokenId);
                var result = false;
                if (refreshToken != null)
                {
                    _repository.DeleteItem(refreshToken);
                    result = _unitOfWork.SaveChanges() > 0;
                }
    
                return Task.FromResult(result);
            }
        }

      思路是通过注入ICustomerIdentityStore(IUserStore)构造出UserManager实例

      6.使用时直接使用IAuthRepository接口就好。

      这样所有的操作都控制自己的代码里,不再需要去改表名,重新映射字段,维护多个上下文了。

    有问题欢迎讨论

    谢谢

  • 相关阅读:
    WebRTC的一个例子
    Gerrit增加SSL证书
    Ruby on Rails 创建https应用
    使用Ruby来实现批量更新AD中字段
    pg gem 安装(postgresql94)
    Spark源码剖析(一):如何将spark源码导入到IDEA中
    Scala入门系列(十三):类型参数
    Scala入门系列(十二):隐式转换
    Scala 安装 Exception in thread "main" java.lang.VerifyError: Uninitialized object exists on backward branch 96
    Scala入门系列(十一):模式匹配
  • 原文地址:https://www.cnblogs.com/laynehu/p/layne_customerauth.html
Copyright © 2020-2023  润新知