Asp.Net 5 Identity 快速集成
使用VS创建Asp.Net 5项目时,默认会使用Identity作为用户验证的基础,以前微软一直把用户信息定得很死板,没法灵活的适应于生产,但自从.net 5出来后,就作了很大的改动,现在可以很方便的使用起来:
Idenity 启用
在Startup.ConfigureServices方法中,会找到以下代码:
services.AddIdentity<ApplicationUser,IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
ApplicationUser 为用户对象
IdentityRole 为角色对象
ApplicationDbContext 为用户与角色读取的EF对象
打开AccountController,会发现两个新对象:
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
如果我们直接修改这几个类型,肯定会碰到很多问题,那下面咱们就一步一步来自定义一下:
首先,Identity本身对用户以及角色类没有什么限制,但是想摆脱IdentityUser,IdentityRole的限制就得自己实现IUserStore<TUser>,IUserRole<IRoleStore>两个接口了。
public class UserStore : IUserStore<UserInfo>
{
private bool _disposed;
public UserStore(ApplicationDbContext context)
{
Context = context;
}
public DbContext Context { get; private set; }
protected virtual IQueryable<UserInfo> Users
{
get { return Context.Set<UserInfo>(); }
}
protected void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
}
#region IUserStore
public Task<IdentityResult> CreateAsync(UserInfo user, CancellationToken cancellationToken)
{
return Task.FromResult(IdentityResult.Success);
}
public Task<IdentityResult> DeleteAsync(UserInfo user, CancellationToken cancellationToken)
{
return Task.FromResult(IdentityResult.Success);
}
public void Dispose()
{
_disposed = true;
}
public Task<UserInfo> FindByIdAsync(string userId, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
int user_id = Convert.ToInt32(userId);
return Users.FirstOrDefaultAsync(u => u.User_Id == user_id, cancellationToken);
}
public Task<UserInfo> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
return Users.FirstOrDefaultAsync(u => u.User_Name == normalizedUserName, cancellationToken);
}
public Task<string> GetNormalizedUserNameAsync(UserInfo user, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
return Task.FromResult(user.User_Name);
}
public Task<string> GetUserIdAsync(UserInfo user, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
return Task.FromResult(user.User_Id.ToString());
}
public Task<string> GetUserNameAsync(UserInfo user, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
return Task.FromResult(user.NickName);
}
public Task SetNormalizedUserNameAsync(UserInfo user, string normalizedName, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
user.User_Name = normalizedName;
return Task.FromResult(0);
}
public Task SetUserNameAsync(UserInfo user, string userName, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
user.TrueName = userName;
return Task.FromResult(0);
}
public Task<IdentityResult> UpdateAsync(UserInfo user, CancellationToken cancellationToken)
{
return Task.FromResult(IdentityResult.Success);
}
#endregion
}
public class RoleStore : IRoleStore<Roles>
{
private bool _disposed;
public RoleStore(ApplicationDbContext context)
{
Context = context;
}
public DbContext Context { get; private set; }
protected virtual IQueryable<Roles> Roles
{
get { return Context.Set<Roles>(); }
}
protected void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
}
public Task<IdentityResult> CreateAsync(Roles role, CancellationToken cancellationToken)
{
return Task.FromResult(IdentityResult.Success);
}
public Task<IdentityResult> DeleteAsync(Roles role, CancellationToken cancellationToken)
{
return Task.FromResult(IdentityResult.Success);
}
public void Dispose()
{
_disposed = true;
}
public Task<Roles> FindByIdAsync(string roleId, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
int id = Convert.ToInt32(roleId);
return Roles.FirstOrDefaultAsync(u => u.Role_Id == id, cancellationToken);
}
public Task<Roles> FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
return Roles.FirstOrDefaultAsync(u => u.Code == normalizedRoleName, cancellationToken);
}
public Task<string> GetNormalizedRoleNameAsync(Roles role, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
return Task.FromResult(role.Code);
}
public Task<string> GetRoleIdAsync(Roles role, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
return Task.FromResult(role.Role_Id.ToString());
}
public Task<string> GetRoleNameAsync(Roles role, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
return Task.FromResult(role.Name);
}
public Task SetNormalizedRoleNameAsync(Roles role, string normalizedName, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
role.Code = normalizedName;
return Task.FromResult(0);
}
public Task SetRoleNameAsync(Roles role, string roleName, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
role.Name = roleName;
return Task.FromResult(0);
}
public Task<IdentityResult> UpdateAsync(Roles role, CancellationToken cancellationToken)
{
return Task.FromResult(IdentityResult.Success);
}
}
然后将Startup配置改成:
services.AddIdentity<UserInfo, Roles>().AddUserStore<Services.UserStore>().AddRoleStore<RoleStore>();
这时,你已经完成了用户以及角色的自定义了,是不是很简单呢。
如果你还需要使用UserManager<UserInfo>进行密码验证操作,你还需要在UserStore中实现 IUserPasswordStore<TUser>,如果需要自定义加密方式,则需要实现IPasswordHasher<TUser>,然后在配置中添加你的类就行了。
services.AddScoped<IPasswordHasher<UserInfo>, MyPasswordHasher>()