User.Claims.FirstOrDefault()。在登录操作(ASP.NET 身份 3)时值为空?

User.Claims.FirstOrDefault().Value is null at Login action (ASP.NET Identity 3)?

在使用 "Individual User Account" 创建默认 ASP.NET 核心后,我试图在登录操作中从用户对象获取 "id" 值,它始终为 returns 空值。该行是 (var objUser = User.Claims.FirstOrDefault().Value;)

[HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        if (ModelState.IsValid)
        {
            // This doesn't count login failures towards account lockout
            // To enable password failures to trigger account lockout, set lockoutOnFailure: true
            var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);


            if (result.Succeeded)
            {

                var objUser = User.Claims.FirstOrDefault().Value;

                _logger.LogInformation(1, "User logged in.");
                return RedirectToLocal(returnUrl);
            }
            if (result.RequiresTwoFactor)
            {
                return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
            }
            if (result.IsLockedOut)
            {
                _logger.LogWarning(2, "User account locked out.");
                return View("Lockout");
            }
            else
            {
                ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                return View(model);
            }
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

从 Home/Index

等其他操作访问时,用户对象不为空
public IActionResult Index()
    {
        var x = User.Claims.FirstOrDefault().Value;
        return View();
    }

有没有办法在 result.Succeeded 之后在登录操作中拥有用户对象?

谢谢, AG

我想我找到了答案。

var u = await _userManager.FindByEmailAsync(model.Email);
var u_Id = u.Id;

谢谢, AG

我认为这里的问题是,在用户登录时创建了 claimsprincipal,并且 cookie 身份验证中间件将其序列化为身份验证 cookie,该 cookie 添加到响应中,因此它作为响应。

由于 cookie 的机制,在浏览器将其传回服务器的下一个请求之前,您无法读取 cookie。这是因为您在将 cookie 传回 Web 浏览器的 Response 上设置了 cookie,并且您在 Web 浏览器将 cookie 传递给服务器的 Request 上读取了 cookie。在 post 登录时浏览器还没有通过身份验证 cookie,因为它还没有收到它。您已将其设置在响应中,但如前所述,要从服务器代码访问它,它来自请求而不是响应。

在下一个请求中,cookie 作为 header 传递,然后 cookie 身份验证中间件可以将其从 cookie 反序列化为 ClaimsPrincipal,这就是您的代码中的 "User"控制器。因此,填充的用户和声明在下一个请求之前不可用,然后您可以从请求而不是响应中获取它。

因此,例如,如果您需要根据登录期间分配的声明选择重定向到哪里,您可以这样做的一种方法是重定向到另一个操作,并且该操作是一个新请求,因此可以访问从 cookie 中反序列化的 claimsprincipal,然后可以根据声明再次重定向。缺点是双重重定向。

您也可以按照您在自己的答案中显示的那样查找用户,如果这能满足您的需要,但是您得到的是 ApplicationUser 或 class 代表您的用户的任何东西,这不是一回事作为 ClaimsPrincipal。