ASP.NET Core 6无需登出更新Claim:验证Authenticator后修改amr无效
问题原因
直接修改this.User.Identity里的声明不会生效,因为当前请求的User对象是基于已有的认证票据生成的副本,修改它仅对当前请求的内存对象有效,跳转后新请求会重新从认证Cookie(或Token)加载原有声明,所以看不到更新后的结果。
解决方案
要让声明更新持久化并在后续请求中生效,需要更新用户存储的声明,并重新生成认证票据、更新认证Cookie。修改代码如下:
[HttpPost] [AllowAnonymous] public async Task<ActionResult> EnableAuthenticator(EnableAuthenticatorViewModel enableAuthenticatorViewModel) { var user = await _userManager.GetUserAsync(User); if (user == null) { return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } if (!ModelState.IsValid) { await LoadSharedKeyAndQrCodeUriAsync(user, enableAuthenticatorViewModel); return View(enableAuthenticatorViewModel); } // Strip spaces and hyphens var verificationCode = enableAuthenticatorViewModel.Input.Code.Replace(" ", string.Empty).Replace("-", string.Empty); var is2faTokenValid = await _userManager.VerifyTwoFactorTokenAsync( user, _userManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode); if (!is2faTokenValid) { ModelState.AddModelError("Input.Code", "Verification code is invalid."); await LoadSharedKeyAndQrCodeUriAsync(user, enableAuthenticatorViewModel); return View(enableAuthenticatorViewModel); } await _userManager.SetTwoFactorEnabledAsync(user, true); var userId = await _userManager.GetUserIdAsync(user); TempData["StatusMessage"] = "Your authenticator app has been verified."; // --- 替换原声明更新代码为以下内容 --- // 1. 更新用户在数据库中的声明 var existingAmrClaim = (await _userManager.GetClaimsAsync(user)) .FirstOrDefault(c => c.Type == "amr"); if (existingAmrClaim != null) { await _userManager.RemoveClaimAsync(user, existingAmrClaim); } await _userManager.AddClaimAsync(user, new Claim("amr", "mfa")); // 2. 重新生成认证票据并更新Cookie var claimsIdentity = new ClaimsIdentity( await _userManager.GetClaimsAsync(user), CookieAuthenticationDefaults.AuthenticationScheme); var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); await HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal, new AuthenticationProperties { // 保持原有认证的持久化设置,可根据实际情况调整 IsPersistent = HttpContext.User.Identity.IsAuthenticated, ExpiresUtc = DateTimeOffset.UtcNow.AddDays(7) }); // --- 声明更新代码结束 --- return RedirectToAction("Users","Admin"); }
关键说明
- 先通过
_userManager更新用户在数据库中的声明,确保数据持久化; - 调用
HttpContext.SignInAsync重新生成认证Cookie,让后续请求能加载到新的声明; - 如果你的项目使用JWT而非Cookie认证,需要重新签发JWT Token并返回给客户端,而非更新Cookie。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

