您的位置:首页 > 编程语言 > ASP

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

2015-11-26 10:57 609 查看
  最近一个项目需要在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接口就好。

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

有问题欢迎讨论

谢谢
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: