You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Identity Server 4使用数据库用户异步请求密码令牌异常问题咨询

问题定位与修复方案

1. 配置顺序错误

当前Startup中服务注册顺序错误,AddIdentity必须放在AddIdentityServer之前,否则AddAspNetIdentity<ApplicationUser>无法正常依赖已注册的Identity服务,正确顺序如下:

// 先注册ASP.NET Core Identity
services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<DataContext>()
        .AddDefaultTokenProviders();

// 再注册IdentityServer
services.AddIdentityServer()
    //Configuration Store: clients and resources
    .AddConfigurationStore(options =>
    {
        options.ConfigureDbContext = builder => builder.UseMySQL(connectionString, opt => opt.MigrationsAssembly(migrationAssembly));
    })
    //Oprerationals Store: tokens, consets, codes, etc
    .AddOperationalStore(options =>
    {
        options.ConfigureDbContext = builder => builder.UseMySQL(connectionString, opt => opt.MigrationsAssembly(migrationAssembly));
    })
    .AddAspNetIdentity<ApplicationUser>()
    .AddDeveloperSigningCredential();

2. 自定义用户模型属性冲突

你继承了IdentityUser但重复定义了Id、Email、UserName、PasswordHash等父类已有的属性,且自定义了Id为int类型,需要修改为泛型版本的父类继承,删除重复属性定义:

// 用IdentityUser<int>指定主键类型为int,仅保留自定义扩展字段
public class ApplicationUser : IdentityUser<int>
{
    public string Name { get; set; }
    public string AvatarUrl { get; set; }
}

对应你的DataContext需要改为继承IdentityDbContext<ApplicationUser, IdentityRole<int>, int>,保证主键类型全局统一。

3. 自定义密码哈希和Identity体系不兼容

你自己实现的CreatePasswordHash、VerifyPasswordHash用的是自定义哈希规则,而IS4集成AddAspNetIdentity后,密码校验走ASP.NET Core Identity自带的哈希逻辑,两者不兼容导致密码校验永远失败,需要修改注册、登录逻辑复用Identity自带能力:

注册逻辑修改

// 注入UserManager<ApplicationUser>替代手动操作DbContext
public async Task<ServiceResponse<int>> Register(ApplicationUser user, string password)
{
    ServiceResponse<int> response = new ServiceResponse<int>();
    if (await UserExists(user.Email))
    {
        response.Success = false;
        response.Message = "User already exists.";
        return response;
    }
    user.UserName = user.Email;
    // 用UserManager自动处理密码哈希、用户存储
    var createResult = await _userManager.CreateAsync(user, password);
    if (!createResult.Succeeded)
    {
        response.Success = false;
        response.Message = string.Join(";", createResult.Errors.Select(x => x.Description));
        return response;
    }
    response.Data = user.Id;
    return response;
}

登录逻辑修改

public async Task<ServiceResponse<string>> Login(string email, string password)
{
    var response = new ServiceResponse<string>();
    var user = await _userManager.FindByEmailAsync(email);
    if (user == null)
    {
        response.Success = false;
        response.Message = "User not found.";
    }
    else if (!await _userManager.CheckPasswordAsync(user, password))
    {
        response.Success = false;
        response.Message = "Wrong password.";
    }
    else
    {
        response.Data = await CreateToken(email, password);
    }
    return response;
}

4. Config配置与持久化问题

你已经配置了AddConfigurationStore将客户端、资源等配置持久化到数据库,需要执行初始化逻辑把Config类中的IdentityResources、ApiScopes、ApiResources、Clients写入数据库,否则IS4读取不到配置会校验失败。另外你已经集成了ASP.NET Identity,不需要再保留GetUsers返回TestUser的代码,可以直接删除。

5. Token生成逻辑优化

不需要在服务端内部发起HTTP请求调用IS4的Token端点,直接注入IS4的ITokenService在内存生成Token即可,减少不必要的网络开销。

适配确认

不需要完全重写注册登录逻辑,仅需要将原有自定义数据库操作替换为Identity自带的UserManager、SignInManager相关方法即可适配IS4;另外需要确保数据库已经执行了Identity和IS4的迁移,生成了对应的用户表、配置表、操作存储表。
注:资源所有者密码流官方不推荐用于生产环境,生产环境建议改用Authorization Code流

内容的提问来源于stack exchange,提问作者Adrian Tocu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 16:06:03