Demo https://github.com/MartinAaron/data_collection
1、自定义身份校验
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
//grant_type basic
new Client
{
ClientId = "xczx",
AccessTokenLifetime = 36000,
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("xczx".Sha256()),
},
AllowedScopes = {"api"}
},
// grant_type password
new Client()
{
ClientId = "client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("_123456".Sha256())
},
AllowedScopes =
{
"api", IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
}
};
}
// ...
//StartUp.cs
services.AddScoped<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>();
services.AddScoped<IProfileService, ProfileServices>();
var builder = services.AddIdentityServer()
.AddInMemoryClients(Conf.GetClients())
.AddInMemoryIdentityResources(Conf.GetIdentityResourceResources())
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()
.AddInMemoryApiResources(Conf.GetApiResources())
.AddInMemoryApiScopes(Conf.ApiScopes)
.AddProfileService<ProfileServices>();
使用 ResourceOwnerPassword 类型 需要实现 IResourceOwnerPasswordValidator与IProfileService接口,进行业务密码验证与身份获取。
//ResourceOwnerPasswordValidator
public ResourceOwnerPasswordValidator(UserRepository userRepository)
{
_userRepository = userRepository;
}
private readonly UserRepository _userRepository;
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
var user = await _userRepository.GetListByField("account", context.UserName);
if (user.Count == 0)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant,
"账号输入错误");
}
else if (user.First().Password != context.Password.ToMD5String())
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant,
"密码错误")
;
}
else
{
context.Result = new GrantValidationResult(
subject: context.UserName,
authenticationMethod: OidcConstants.AuthenticationMethods.Password);
}
}
//ProfileServices
public ProfileServices(UserRepository userRepository)
{
_userRepository = userRepository;
}
private readonly UserRepository _userRepository;
public async Task<List<Claim>> GetClaimsFromUserAsync(User user)
{
var claims = new List<Claim>
{
new Claim(JwtClaimTypes.Id, user.Id.ToString()),
new Claim(JwtClaimTypes.NickName, user.RealName),
new Claim(type: JwtClaimTypes.Role, user.RoleId ?? ""),
new Claim(type: JwtClaimTypes.Profile, user.DepartmentId ?? "")
};
await Task.CompletedTask;
return claims;
}
/// <summary>
/// http://localhost:5002/connect/userinfo
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var userAccount = context.Subject.Claims.FirstOrDefault(c => c.Type == "sub").Value;
var user = await _userRepository.GetListByField("account", userAccount);
context.IssuedClaims = await GetClaimsFromUserAsync(user.First());
}
public async Task IsActiveAsync(IsActiveContext context)
{
var userAccount = context.Subject.Claims.FirstOrDefault(c => c.Type == "sub").Value;
var user = await _userRepository.GetListByField("account", userAccount);
context.IsActive = user.Any();
}
别忘记注入两个实现类
获取Token http://localhost:5002/connect/token
通过 access_token 获取用户信息
这里 token 不加 Bearer和空格