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

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");
}
关键说明
  1. 先通过_userManager更新用户在数据库中的声明,确保数据持久化;
  2. 调用HttpContext.SignInAsync重新生成认证Cookie,让后续请求能加载到新的声明;
  3. 如果你的项目使用JWT而非Cookie认证,需要重新签发JWT Token并返回给客户端,而非更新Cookie。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 15:01:32