IdentityServer4提供的demo 是用的自己的表结构,但是对于我们来说就不是很适用了,研究了下他的源码发现他的密码模式,大概就是更改下面几个方法大,致就是读取数据库数据,与context.username ,password,进行比对,一致则通过,不一致就是失败
public class ProfileService : IProfileService { //services private IUserRepository _userRepository = new UserRepository(); //build claims array from user data public static Claim[] GetUserClaims(User user) { var c = new Claim[] { }; c[0] = new Claim("user_id", "465464"); c[1] = new Claim("sub", "465464"); return c; } /// <summary> /// 每当请求有关用户的声明时(例如,在令牌创建期间或通过userinfo端点),都会调用此方法 /// </summary> /// <param name="context"></param> /// <returns></returns> public async Task GetProfileDataAsync(ProfileDataRequestContext context) { try { //depending on the scope accessing the user data. if (!string.IsNullOrEmpty(context.Subject.Identity.Name)) { //get user from db (in my case this is by email) var user = await _userRepository.FindAsync(45121); if (user != null) { var claims = GetUserClaims(user); //set issued claims to return context.IssuedClaims = claims.Where(x => context.RequestedClaimTypes.Contains(x.Type)).ToList(); } } else { //get subject from context (this was set ResourceOwnerPasswordValidator.ValidateAsync), //where and subject was set to my user id. var userId = context.Subject.Claims.FirstOrDefault(x => x.Type == "sub"); if (!string.IsNullOrEmpty(userId?.Value) && long.Parse(userId.Value) > 0) { //get user from db (find user by user id) var user = await _userRepository.FindAsync(long.Parse(userId.Value)); // issue the claims for the user if (user != null) { var claims = ResourceOwnerPasswordValidator.GetUserClaims(user); context.IssuedClaims = claims.Where(x => context.RequestedClaimTypes.Contains(x.Type)).ToList(); } } } } catch (Exception ex) { //log your error } } //check if user account is active. public async Task IsActiveAsync(IsActiveContext context) { try { //get subject from context (set in ResourceOwnerPasswordValidator.ValidateAsync), var userId = context.Subject.Claims.FirstOrDefault(x => x.Type == "user_id"); if (!string.IsNullOrEmpty(userId?.Value) && long.Parse(userId.Value) > 0) { var user = await _userRepository.FindAsync(long.Parse(userId.Value)); if (user != null) { if (user.IsActive) { context.IsActive = user.IsActive; } } } } catch (Exception ex) { //handle error logging } } }
public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator { private IUserRepository _userRepository = new UserRepository(); //build claims array from user data //build claims array from user data public static Claim[] GetUserClaims(User user) { var c = new Claim[] { }; c[0] = new Claim("user_id", "465464"); c[1] = new Claim("sub", "465464"); return c; } //this is used to validate your user account with provided grant at /connect/token public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context) { try { //get your user model from db (by username - in my case its email) var user = await _userRepository.FindAsync(1241); if (user != null) { //check if password match - remember to hash password if stored as hash in db if (true) { //set the result context.Result = new GrantValidationResult( subject: user.Id.ToString(), authenticationMethod: "custom", claims: GetUserClaims(user)); return; } context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Incorrect password"); return; } context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "User does not exist."); return; } catch (Exception ex) { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Invalid username or password"); } } }
1 //add identity server 4 2 services.AddIdentityServer() 3 .AddInMemoryApiScopes(Config.GetApiScopes()) 4 .AddInMemoryApiResources(Config.GetApiResources()) 5 .AddInMemoryIdentityResources(Config.GetIdentityResources()) 6 .AddInMemoryClients(Config.GetClients()) 7 .AddDeveloperSigningCredential(persistKey: false) 8 .AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()//用户校验 9 .AddProfileService<ProfileService>();
参考资料:https://buildmedia.readthedocs.org/media/pdf/identityserver4/release/identityserver4.pdf