经过很多挣扎(以及大量的指导,指南等),我设法设置了一个小型的.NET Core REST Web API,当存储的用户名和密码有效时,使用身份验证控制器颁发JWT令牌。
令牌将用户ID存储为子声明。
我还设法设置了Web API,以便在方法使用Authorize注释时验证这些标记。
app.UseJwtBearerAuthentication(...)
现在我的问题是:我如何在我的控制器(在一个Web API中)中读取用户id(存储在主题声明中)?
这基本上是这个问题(如何在ASP中获得当前用户。NET Core)但我需要一个Web api的答案。而且我没有UserManager。所以我需要从某个地方阅读主题声明。
似乎很多人都在关注这个问题,所以我想分享一些我不久前问这个问题后所学到的更多信息。它让一些事情变得更加清晰(至少对我来说),而不是那么明显(对我来说是。NET新手)。
正如Marcus Höglund在评论中提到的:
在ASP。NET Core Mvc和Web Api合并使用同一控制器。
那绝对是真的,绝对正确。
因为它在. NET和. NET Core之间都是一样的。
回到我之前,我还是.NET Core的新手,实际上是整个.NET世界。缺少的重要信息是,在.NET和.NET Core中,所有身份验证都可以通过其ClaimsIdentity,ClaimsPrinciple和Claims.Properties缩减到System.Security.Claims命名空间。因此,它用于两种.NET Core控制器类型(API和MVC或Razor或...),并且可以通过HttpContext.User
访问。
所有教程都忽略了一个重要的侧记。
因此,如果您开始在.NET中使用JWT令牌,不要忘记对ClaimsIdentity、ClaimsPrinciple和Claim.Properties也充满信心。都是关于这个的。现在你知道了。赫林格在其中一条评论中指出了这一点。
所有基于声明的认证中间件将(如果正确实现)填充< code>HttpContext。身份验证期间收到声明的用户。
据我所知,这意味着可以安全地信任HttpContext.User
中的值。但请稍候,了解在选择中间件时应该考虑什么。已经有很多不同的身份验证中间件可用(除了.UseJwtAuthentication()
)。
使用小型自定义扩展方法,您现在可以像这样获取当前用户ID(更准确的主题声明)
public static string SubjectId(this ClaimsPrincipal user) { return user?.Claims?.FirstOrDefault(c => c.Type.Equals("sub", StringComparison.OrdinalIgnoreCase))?.Value; }
或者您使用Ateik答案中的版本。
但等待:有一件奇怪的事
接下来让我困惑的是:根据OpenID Connect规范,我正在寻找“子”声明(当前用户),但找不到。就像Honza Kalfus在回答中做不到的。
为什么?
因为微软“有时候”“有点”与众不同。或者至少他们做了更多(意想不到的)事情。比如原问题中提到的官方微软JWT承载认证中间件。微软决定转换他们所有官方认证中间件中的声明(声明的名称)(出于兼容性原因,我不知道更多细节)。
您不会找到“子”声明(尽管它是OpenID Connect指定的单个声明)。因为它被转换为这些花哨的声明类型。这并不全是坏事,如果您需要将不同的声明映射到唯一的内部名称,它允许您添加映射。
要么您坚持使用Microsoft命名(并且在添加/使用非Microsoft中间件时必须注意这一点),要么您了解如何转换Microsoft中间件的声明映射。
在JwtBearerAuthentication的情况下,它已经完成(在启动的早期或者至少在添加中间件之前完成):
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
如果你想坚持微软命名主题声明(不要打败我,我现在不确定 Name 是否正确映射):
public static string SubjectId(this ClaimsPrincipal user) { return user?.Claims?.FirstOrDefault(c => c.Type.Equals(ClaimTypes.NameIdentifier, StringComparison.OrdinalIgnoreCase))?.Value; }
请注意,其他答案使用更高级,更方便的FindFirst方法。虽然我的代码示例显示了它,但没有那些,但你应该使用它们。
因此,您的所有声明都存储在 HttpContext.User
中并可访问(通过一个名称或另一个名称)。
但是我的代币在哪里?
我不知道其他中间件,但JWT载体认证允许保存每个请求的令牌。但这需要激活(在< code >启动中。配置服务(...)。
services
.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options => options.SaveToken = true);
然后可以通过以下方式访问字符串(或null)形式的实际令牌(以其所有隐含形式)
HttpContext.GetTokenAsync("Bearer", "access_token")
这种方法有一个旧版本(这在。NET Core 2.2无弃用警告)。
如果您需要从此字符串中解析和提取值,问题如何解码 JWT 令牌可能会有所帮助。
好吧,我希望该摘要对您有所帮助。
您可以使用此方法:
var email = User.FindFirst("sub")?.Value;
在我的例子中,我使用电子邮件作为唯一值
接受的答案对我不起作用。我不确定这是由我使用 .NET Core 2.0 还是其他原因引起的,但看起来框架将主题声明映射到 NameIdentifier 声明。所以,以下内容对我有用:
string userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
请注意,这假定在 JWT 中设置了主题子
声明,并且其值是用户的 ID。
默认情况下,中的JWT身份验证处理程序。NET会将JWT访问令牌的子声明映射到< code >系统。security . claims . claim types . name identifier 声明类型。[来源]
GitHub上还有一个讨论主题,他们得出结论认为这种行为令人困惑。
IServiceProvider是一个具有单一方法的接口: 它用于创建已注册的类型的实例。NET Core原生DI容器。 可以通过调用IServiceCollection的方法来获得IServiceProvider自身的实例。它似乎是通过框架的实例神奇地调用的。 我想创建一个的实例,而不需要方法。我需要它来解决集成测试程序集中的依赖关系。在这种情况下有可能得到它吗?
问题内容: 我在Linux上使用libnuma。我的线程应该知道它们正在运行的节点/核心。是否可以某种方式获取当前线程的节点/核心?我已经看过文档,但是没有找到这样的功能… 问题答案: 我找到了这个解决方案: 然后,如果需要cpu的节点,则可以使用numa.h:
我有一个Spring Boot REST应用程序,它使用JWT令牌进行授权。我想使用AuthenticationPrincipal注释获取控制器中当前登录的用户。但如果我从loadUserByUsername返回自定义模型,并且auth停止工作,它总是返回null。我的模型实现了用户详细信息。 我试图扩展组织。springframework。安全果心用户详细信息。但我从JWTAuthenticat
您好,我正在使用平均堆栈和jwt登录,我想限制一些数据只有userRole'admin'这是我的user.js 这就是我验证jwt令牌的方法 这是我希望使用verifyToken函数仅为'admin'角色限制的数据 我的问题是,我如何访问当前登录的用户信息,并仅使管理员可读的/特殊的
我正在尝试通过刷新令牌和JWT在. NET Core 2.1中实现基于令牌的身份验证。 这就是我实施JWT令牌的方式: 启动.cs 令牌生成: 我正在给他回复正确的数值。 但是一分钟后,我在 Postman 中为授权设置了相同的令牌,它可以工作。如果令牌已过期,则不应过期。 我使用不记名令牌作为认证。 我做错了什么?需要方向。
我已经创建了自定义中间件类来验证JWT令牌。我在