如何基于用户凭证(邮箱、密码)及ID生成Access Token?IdentityServer方案咨询
基于IdentityServer实现带自定义ID的Access Token生成方案
1. 扩展用户验证流程注入自定义信息
使用Resource Owner Password Credentials授权模式时,自定义IResourceOwnerPasswordValidator来处理邮箱+密码验证,同时加载目标subscriptionId并注入到用户声明中:
public class CustomResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator { private readonly IUserRepository _userRepository; public CustomResourceOwnerPasswordValidator(IUserRepository userRepository) { _userRepository = userRepository; } public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context) { // 验证邮箱与密码合法性 var user = await _userRepository.GetUserByEmailAndPasswordAsync(context.UserName, context.Password); if (user != null) { // 将subscriptionId作为自定义声明添加到验证结果 context.Result = new GrantValidationResult( subject: user.Id.ToString(), authenticationMethod: "password", claims: new List<Claim> { new Claim("subscriptionId", user.SubscriptionId.ToString()) }); } else { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Invalid email or password"); } } }
在DI容器中注册这个自定义验证器,替换默认实现:
services.AddIdentityServer() .AddResourceOwnerValidator<CustomResourceOwnerPasswordValidator>();
2. 配置ApiResource允许自定义声明
确保目标ApiResource包含subscriptionId作为允许的用户声明,这样生成的Access Token会携带该字段:
public static IEnumerable<ApiResource> GetApiResources() { return new List<ApiResource> { new ApiResource("your-api-name") { UserClaims = { "subscriptionId" } } }; }
3. 自定义令牌生成器(可选,用于更复杂场景)
如果需要对令牌生成逻辑做深度定制,可以实现ITokenGenerator接口并替换默认服务:
public class CustomTokenGenerator : ITokenGenerator { private readonly ITokenService _tokenService; private readonly IUserClaimsPrincipalFactory _claimsFactory; public CustomTokenGenerator(ITokenService tokenService, IUserClaimsPrincipalFactory claimsFactory) { _tokenService = tokenService; _claimsFactory = claimsFactory; } public async Task<Token> GenerateTokenAsync(TokenCreationRequest request) { // 可在此处手动修改Claims集合,注入subscriptionId var principal = await _claimsFactory.CreateAsync(request.Subject); principal.Identities.First().AddClaim(new Claim("subscriptionId", request.Subject.FindFirstValue("subscriptionId"))); request.Subject = principal; return await _tokenService.CreateTokenAsync(request); } }
注册自定义生成器:
services.AddTransient<ITokenGenerator, CustomTokenGenerator>();
内容的提问来源于stack exchange,提问作者Sachin Gaikwad
相关产品推荐
相关产品推荐

