理解了完整的密码授权模式流程后,使用自定义的用户体系就得心应手了,下面就开始完整的实现自定义帐户授权。
三、设计自定义的账户信息并应用为了演示方便,我这里就设计简单的用户帐户信息,作为自定义的哦帐户基础,如果正式环境中使用,请根据各自业务使用各自的帐户体系即可。
-- 创建用户表 CREATE TABLE CzarUsers ( Uid INT IDENTITY(1,1), --用户主键 uAccount varchar(11), --用户账号 uPassword varchar(200), --用户密码 uNickName varchar(50), --用户昵称 uMobile varchar(11), --用户手机号 uEmail varchar(100), --用户邮箱 uStatus int not null default(1) -- 用户状态 1 正常 0 不可用 )添加用户实体代码如下所示。
/// <summary> /// 授权用户信息 /// </summary> public class CzarUsers { public CzarUsers() { } public int Uid { get; set; } public string uAccount { get; set; } public string uPassword { get; set; } public string uNickName { get; set; } public string uMobile { get; set; } public string uEmail { get; set; } public string uStatus { get; set; } }下面开始密码授权模式开发,首先需要重新实现IResourceOwnerPasswordValidator接口,使用我们定义的用户表来验证请求的用户名和密码信息。
/// <summary> /// 金焰的世界 /// 2018-12-18 /// 自定义用户名密码校验 /// </summary> public class CzarResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator { private readonly ICzarUsersServices _czarUsersServices; public CzarResourceOwnerPasswordValidator(ICzarUsersServices czarUsersServices) { _czarUsersServices = czarUsersServices; } /// <summary> /// 验证用户身份 /// </summary> /// <param></param> /// <returns></returns> public Task ValidateAsync(ResourceOwnerPasswordValidationContext context) { var user = _czarUsersServices.FindUserByuAccount(context.UserName, context.Password); if (user != null) { context.Result = new GrantValidationResult( user.Uid.ToString(), OidcConstants.AuthenticationMethods.Password, DateTime.UtcNow); } return Task.CompletedTask; } }编写完自定义校验后,我们需要注入到具体的实现,详细代码如下。
public void ConfigureServices(IServiceCollection services) { services.AddSingleton(Configuration); services.Configure<CzarConfig>(Configuration.GetSection("CzarConfig")); services.AddIdentityServer(option=> { option.PublicOrigin = Configuration["CzarConfig:PublicOrigin"]; }) .AddDeveloperSigningCredential() .AddDapperStore(option => { option.DbConnectionStrings = Configuration["CzarConfig:DbConnectionStrings"]; }) //使用自定义的密码校验 .AddResourceOwnerValidator<CzarResourceOwnerPasswordValidator>() ; // .UseMySql(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }剩下的就是把ICzarUsersServices接口实现并注入即可。详细代码如下。
/// <summary> /// 金焰的世界 /// 2018-12-18 /// 用户服务接口 /// </summary> public interface ICzarUsersServices { /// <summary> /// 根据账号密码获取用户实体 /// </summary> /// <param>账号</param> /// <param>密码</param> /// <returns></returns> CzarUsers FindUserByuAccount(string uaccount, string upassword); /// <summary> /// 根据用户主键获取用户实体 /// </summary> /// <param>用户标识</param> /// <returns></returns> CzarUsers FindUserByUid(string sub); } /// <summary> /// 金焰的世界 /// 2018-12-18 /// 用户服务实现 /// </summary> public class CzarUsersServices : ICzarUsersServices { private readonly ICzarUsersRepository _czarUsersRepository; public CzarUsersServices(ICzarUsersRepository czarUsersRepository) { _czarUsersRepository = czarUsersRepository; } /// <summary> /// 根据账号密码获取用户实体 /// </summary> /// <param>账号</param> /// <param>密码</param> /// <returns></returns> public CzarUsers FindUserByuAccount(string uaccount, string upassword) { return _czarUsersRepository.FindUserByuAccount(uaccount, upassword); } /// <summary> /// 根据用户主键获取用户实体 /// </summary> /// <param>用户标识</param> /// <returns></returns> public CzarUsers FindUserByUid(string sub) { return _czarUsersRepository.FindUserByUid(sub); } }