【问题标题】:How to get current UserId in Identity 3.0? User.GetUserId returns null如何在 Identity 3.0 中获取当前的 UserId? User.GetUserId 返回 null
【发布时间】:2016-06-05 06:35:36
【问题描述】:

我需要获取提出请求的用户的 ID。 在以前的 Identity 版本中,我可以这样做:

User.Identity.GetUserId();

但它似乎不再可用了。

还有类似的:

User.GetUserId();

但它总是返回 null,即使 User.Identity.IsAuthenticated 为 true 并且 User.Identity.Name 设置正确。

我应该用什么来做呢?

编辑: 我的身份验证逻辑基于[default Visual Studio 2015 template],到目前为止我的身份没有太大变化,所以如果你想检查它是如何完成的,你可以在我粘贴的github链接上简单地看到它。

【问题讨论】:

  • 您能发布您的身份验证逻辑吗? GetUserId 从用户声明中检索 Id。
  • @Hazye 你到底想要什么?我的项目是基于默认模板(github.com/MyPCIsBetter/…),到目前为止我没有太大变化,你可以看看那里
  • 我已经使用您提供的模板测试了 User.GetUserId() 并且工作正常。确保当前用户的 ClaimsIdentity 包含 nameidentifier 声明,因为这是上述方法能够检索用户 ID 的方式。
  • @Hazye 好吧,它没有。我现在意识到我正在处理的代码使用基于令牌的身份验证(用于 API),它基于这个答案:stackoverflow.com/questions/29048122/…。 User.GetUserId 在使用原始/内置身份验证的控制器中运行良好,但是当我使用已链接的身份验证时,没有 nameidentifier 也没有 User.GetUserId。看来我需要实现它。
  • @Hezye 你知道如何设置 nameidentifier 声明以使其最终起作用吗?

标签: asp.net asp.net-core asp.net-identity-3


【解决方案1】:

我认为在以前的版本中有一个内置的扩展方法,但他们删除了它。您可以实现自己的来替换它:

using System;
using System.Security.Claims;
using Microsoft.AspNet.Identity;

namespace cloudscribe.Core.Identity
{
    public static class ClaimsPrincipalExtensions
    {
        public static string GetUserId(this ClaimsPrincipal principal)
        {
            if (principal == null)
            {
                throw new ArgumentNullException(nameof(principal));
            }
            var claim = principal.FindFirst(ClaimTypes.NameIdentifier);
            return claim != null ? claim.Value : null;
        }
    }
}

ClaimType.NameIdentifier 应该映射到用户 ID

【讨论】:

  • 在 RC1 中确实存在 GetUserId 扩展,但在 latest code 中他们似乎已将其删除。
  • 看看我的回答。
【解决方案2】:

@乔·奥德特

原来它已经搬到别的地方了。

User.GetUserId => UserManager.GetUserId(User)
User.GetUserName => UserManager.GetUserName(User)
User.IsSignedIn => SignInManager.IsSignedIn(User)

detail on github

【讨论】:

  • 是的,这个变化发生在 rc2 中。对我来说,在 ClaimsPrincipal 上创建扩展方法似乎更好,而不是像在最新的项目模板中那样将 UserManager 和 SignInManager 注入到 _LoginPartial.cshtml 等视图中
  • @JoeAudette 好吧,老实说,我喜欢你的方式。
  • 这是更好的答案,并且在您不使用专有声明协议时有效。这里有很多使用 ClaimTypes.NameIdentifier 常量的建议,如果您使用的是 OpenID 声明,这将不起作用。在这种情况下,标识符声明是“sub”,而不是“schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier”。
【解决方案3】:

根据我们的讨论,您的用户身份似乎不包含 User.GetUserId() 使用的正确声明。

以下是手动设置 NameIdentifier 声明的方法:

// ClaimsIdentity identity = new ClaimsIdentity...

identity.AddClaim(ClaimTypes.NameIdentifier, user.Id);

【讨论】:

  • 是的,它似乎有效。最后。谢谢!但是我仍然不明白在整个身份验证过程中这里到底发生了什么。它是如何工作的,以及有关当前活跃用户的所有这些数据的存储位置。你知道一些很好的资料吗?
  • 这不是 SO 问题的一部分,但您似乎对此有所了解……也许您可以推荐我阅读一下
  • 太棒了。有关用户的数据存储在授权服务器为每个用户生成的令牌中(例如用户 ID)。然后,客户端/用户在 HTTP 请求标头 (web api) 或 cookie (mvc) 中将此令牌传递给服务器。然后,服务器能够验证和解密令牌以获取用户信息。您可以在此处阅读有关基于声明的身份的信息:msdn.microsoft.com/en-us/library/ee517291.aspx
【解决方案4】:

我的目标是在自定义中间件中检索 UserId,这就是我使用的:

httpContext.User.Identity.IsAuthenticated ? 
    httpContext.User.Claims.Where(c => c.Type == ClaimTypes.NameIdentifier).First().Value 
    : Guid.Empty.ToString()

【讨论】:

    【解决方案5】:

    User.Identity.GetUserId(); 在继承Page 的类中可用。

    【讨论】:

    • 继承“Controller”的类呢?
    • 你在用什么? WebForms 还是 MVC?
    【解决方案6】:

    你也可以使用

    User.Identity.Name;
    

    欲了解更多信息,请访问 MSDN

    https://msdn.microsoft.com/en-us/library/system.security.principal.windowsidentity(v=vs.110).aspx

    【讨论】:

    • 是的,但我需要获取 ID ;)
    • 没有。 Identity 3.0 主体不是 Windows 主体,
    • 我只是在调查,但由于问题被标记为 asp.net,我决定留下我的答案。虽然我没有注意到 ID 要求。
    猜你喜欢
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-23
    • 2020-11-16
    • 2015-09-20
    • 2016-09-20
    相关资源
    最近更新 更多