如何在 Identity 3.0 中获取当前的 UserId? User.GetUserId 返回 null

Posted

技术标签:

【中文标题】如何在 Identity 3.0 中获取当前的 UserId? User.GetUserId 返回 null【英文标题】:How to get current UserId in Identity 3.0? User.GetUserId returns 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),它基于这个答案:***.com/questions/29048122/…。 User.GetUserId 在使用原始/内置身份验证的控制器中运行良好,但是当我使用已链接的身份验证时,没有 nameidentifier 也没有 User.GetUserId。看来我需要实现它。 @Hezye 你知道如何设置 nameidentifier 声明以使其最终起作用吗? 【参考方案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 要求。

以上是关于如何在 Identity 3.0 中获取当前的 UserId? User.GetUserId 返回 null的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有实体框架的情况下使用 ASP.NET Identity 3.0 [关闭]

UserManager 在 .Net Identity 中的奇怪行为

如何在 Phonegap 3.0 的 InnApp 浏览器中获取当前 url

如何在 ASP NET CORE 3.0 中获取当前登录的用户 ID?

在 ASP.NET Identity 2.0 中获取当前用户 ID

如何获取 Swift 3.0 中按钮的当前标题,ios 使用 sender.titleForState(.Normal)!