.NET 6下Microsoft Identity多实例环境重置密码令牌偶尔无效问题
排查与配置方案
1. 核心问题定位:DataProtection 密钥不一致
负载均衡多实例环境下,默认的DataProtection会将加密密钥存储在本地服务器文件系统,不同实例的密钥相互独立,导致A实例生成的令牌,B实例用自身密钥无法解密,触发InvalidToken错误。这是此类问题最常见的根源。
2. 排查步骤
- 验证实例间密钥一致性:
在每个Ubuntu实例的~/.aspnet/DataProtection-Keys目录下,查看密钥文件的数量、文件名是否完全相同。若存在差异,说明密钥未实现共享。 - 单实例验证测试:
将负载均衡流量临时切换到单个实例,完整测试密码重置流程。如果全程无InvalidToken错误,即可确认问题由多实例密钥不一致导致。
3. 解决配置:共享DataProtection密钥
方案一:分布式存储共享密钥(推荐)
针对多实例场景,推荐用Redis、SQL Server等分布式存储统一存放DataProtection密钥。以下是Redis配置示例:
using Microsoft.AspNetCore.DataProtection; using StackExchange.Redis; var builder = WebApplication.CreateBuilder(args); // 配置DataProtection使用Redis共享密钥 builder.Services.AddDataProtection() .PersistKeysToStackExchangeRedis( ConnectionMultiplexer.Connect(builder.Configuration["Redis:ConnectionString"]), "DataProtection-Keys") .SetApplicationName("YourUniqueAppName"); // 所有实例必须使用相同的应用名称
注意:
SetApplicationName必须全局统一,否则即使共享存储,不同应用名称会隔离密钥池,导致验证失败。
方案二:手动同步本地密钥(临时过渡)
若暂时无法部署分布式存储,可将其中一个实例的~/.aspnet/DataProtection-Keys目录下所有文件,复制到其他所有实例的对应目录,并确保ASP.NET进程对该目录拥有读写权限。但此方案不支持自动扩容,密钥更新后需手动同步,仅适合临时场景。
4. 其他排查点
- URL编码一致性:检查邮件中的重置链接是否存在双重编码或解码逻辑不一致。生成链接时统一使用
Uri.EscapeDataString,验证时确保解码逻辑匹配。 - 令牌有效期配置:检查
IdentityOptions中的令牌有效期设置,避免因令牌过期引发错误:
builder.Services.Configure<IdentityOptions>(options => { options.Tokens.DataProtectionTokenProvider.TokenLifespan = TimeSpan.FromHours(2); // 根据业务需求调整 });
- 会话粘性(临时方案):若暂时无法配置密钥共享,可开启负载均衡的会话亲和性,确保生成和验证令牌的请求落到同一实例。但此方案会降低系统容错性,仅作为过渡手段。
内容的提问来源于stack exchange,提问作者eBentsa
相关产品推荐
相关产品推荐

