ASP.NET Core 7.0中ConfirmEmailAsync返回无效令牌问题排查
问题原因及解决方案
核心原因
你遇到的问题是生成邮箱确认令牌后修改了用户的SecurityStamp,导致验证时令牌与当前用户的SecurityStamp不匹配。
ASP.NET Core Identity生成邮箱确认令牌时,会结合用户的SecurityStamp(用户安全戳)进行加密。而你在生成令牌后,执行了两个会修改用户数据的操作:
SetTwoFactorEnabledAsync(user, true):启用双因素认证会更新用户的SecurityStampAddToRoleAsync(user, role.Name):给用户添加角色也会触发SecurityStamp更新
这两个操作会改变用户的SecurityStamp,而验证令牌时,Identity会用当前用户的SecurityStamp去解密令牌,自然就会提示"Invalid token"。
解决方案
调整操作顺序,先完成所有用户属性修改和角色分配,再生成邮箱确认令牌。修改注册代码如下:
if (result.Succeeded) { _logger.LogInformation("User created a new account with password."); var userId = await _userManager.GetUserIdAsync(user); // 先执行所有会修改用户的操作 var setTwoFactorResult = await _userManager.SetTwoFactorEnabledAsync(user, true); if (!setTwoFactorResult.Succeeded) { _logger.LogInformation("Two factor authentication failed to set."); } var addToRoleResult = await _userManager.AddToRoleAsync(user, role.Name); if (!addToRoleResult.Succeeded) // 修正原代码判断逻辑错误 { _logger.LogInformation("Role not assigned to user"); } // 最后生成邮箱确认令牌 var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); // 后续生成回调URL、发送邮件的代码保持不变 var callbackUrl = Url.Page( "/Account/ConfirmEmail", pageHandler: null, values: new { area = "Identity", userId = user.Id, code = code, returnUrl = returnUrl }, protocol: Request.Scheme); var confirmationEmail = new EmailInfo() { EmailTo = Input.Email, Subject = "Yellow Fever Account Confirmation Email", Body = $"Please use the following code to confirm your account <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>" }; await _emailService.SendEmailAsync(confirmationEmail); return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl }); }
注:原代码中addToRoleResult.Succeeded的判断逻辑写反了,应该是添加角色失败时才记录日志,上述代码已修正该问题。
内容的提问来源于stack exchange,提问作者user20408154
相关产品推荐
相关产品推荐

