• 还在为身份验证引入的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接口就好。

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

    有问题欢迎讨论

    谢谢

  • 相关阅读:
    Android自定义之仿360Root大师水纹效果
    Android之TextView的Span样式源码剖析
    Android之TextView的样式类Span的使用详解
    随着ScrollView的滑动,渐渐的执行动画View
    仿微信主界面导航栏图标字体颜色的变化
    android自定义之 5.0 风格progressBar
    Android性能优化之内存篇
    Android性能优化之运算篇
    How to install Zabbix5.0 LTS version with Yum on the CentOS 7.8 system?
    How to install Zabbix4.0 LTS version with Yum on the Oracle Linux 7.3 system?
  • 原文地址:https://www.cnblogs.com/laynehu/p/layne_customerauth.html
Copyright © 2020-2023  润新知