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

.NET 6 Identity调用ResetPasswordAsync时遇无效令牌错误

解决.NET 6 Identity重置密码时的"Invalid token"错误

从你提供的代码和数据来看,导致Invalid token的核心原因主要有两个,结合你的猜测逐一解决:

1. 令牌未做URL编码,导致特殊字符被篡改

Identity生成的重置令牌包含+这类URL敏感字符,直接拼接在链接中会被浏览器/邮件客户端自动转义或截断。看你提供的DTO数据,令牌中的+被替换成了换行符,这就是典型的未编码导致的问题。

修复方法:

生成重置链接时,对令牌和邮箱进行URL编码:

public async Task AskPasswordReset(string email)
{
    var user = await _userManager.FindByEmailAsync(email);
    if (user != null)
    {
        var token = await _userManager.GeneratePasswordResetTokenAsync(user);
        // 对令牌和邮箱进行URL编码
        var encodedToken = Uri.EscapeDataString(token);
        var encodedEmail = Uri.EscapeDataString(email);
        var confirmationLink = $"{_configuration["Base Url"]}/ResetPassword?token={encodedToken}&email={encodedEmail}";
        
        var confimEmail = new EmailCommunicationDto
        {
            To = email,
            Body = $"你请求重置密码,请点击以下链接完成操作:{confirmationLink}",
            Subject = "密码重置"
        };
        await _emailSender.SendVerificationEmail(confimEmail);
    }
}

2. 前端解析令牌时的错误处理

你的DTO中令牌出现换行,大概率是邮件客户端将长链接自动换行,或者前端解析URL参数时未正确解码。

修复方法:

  • 前端使用decodeURIComponent()解析URL中的令牌参数,确保完整还原原始令牌;
  • 若邮件客户端自动换行导致链接断裂,可以在邮件正文中将链接放在<pre>标签内,或者提示用户复制完整令牌到重置页面。

3. 验证邮箱强制要求的问题

默认情况下Identity不强制要求邮箱验证即可重置密码,但如果你在Startup/Program.cs中配置了RequireConfirmedEmail,则会导致验证失败:

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

可以在重置密码方法中打印用户的EmailConfirmed属性确认:

public async Task ResetPassword(ResetPasswordDto resetPasswordDto)
{
    var user = await _userManager.FindByEmailAsync(resetPasswordDto.email);
    if (user == null)
    {
        throw new NotFoundException();
    }
    // 检查邮箱是否已验证
    Console.WriteLine($"用户邮箱验证状态:{user.EmailConfirmed}");
    
    var result = await _userManager.ResetPasswordAsync(user, resetPasswordDto.token, resetPasswordDto.newPassword);
    if (!result.Succeeded)
    {
        // 打印所有错误信息,而非只打印ToString()
        foreach (var error in result.Errors)
        {
            Console.WriteLine($"错误代码:{error.Code},错误信息:{error.Description}");
        }
        throw new InvalidCredentialsException();
    }
}

调试建议

在生成令牌、前端接收、后端接收三个环节分别打印令牌内容,对比是否完全一致,快速定位哪一步出现了篡改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 11:55:26