无法使用 ASP.NET Core 从 JWT 令牌获取声明
Posted
技术标签:
【中文标题】无法使用 ASP.NET Core 从 JWT 令牌获取声明【英文标题】:Can't get claims from JWT token with ASP.NET Core 【发布时间】:2017-03-10 11:35:28 【问题描述】:我正在尝试使用 ASP.NET Core 实现一个非常简单的 JWT 不记名身份验证。我从控制器返回的响应有点像这样:
var identity = new ClaimsIdentity();
identity.AddClaim(new Claim(ClaimTypes.Name, applicationUser.UserName));
var jwt = new JwtSecurityToken(
_jwtOptions.Issuer,
_jwtOptions.Audience,
identity.Claims,
_jwtOptions.NotBefore,
_jwtOptions.Expiration,
_jwtOptions.SigningCredentials);
var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);
return new JObject(
new JProperty("access_token", encodedJwt),
new JProperty("token_type", "bearer"),
new JProperty("expires_in", (int)_jwtOptions.ValidFor.TotalSeconds),
new JProperty(".issued", DateTimeOffset.UtcNow.ToString())
);
我有用于传入请求的 Jwt 中间件:
app.UseJwtBearerAuthentication(new JwtBearerOptions
AutomaticAuthenticate = true,
AutomaticChallenge = true,
TokenValidationParameters = tokenValidationParameters
);
这似乎可以使用 authorize 属性保护资源,但声明从未出现。
[Authorize]
public async Task<IActionResult> Get()
var user = ClaimsPrincipal.Current.Claims; // Nothing here
【问题讨论】:
你试过Context.User.Claims
吗?
【参考方案1】:
您不能在 ASP.NET Core 应用程序中使用 ClaimsPricipal.Current
,因为它不是由运行时设置的。您可以阅读https://github.com/aspnet/Security/issues/322 了解更多信息。
请考虑使用User
属性,由ControllerBase
公开。
【讨论】:
【参考方案2】:访问User.Claims
而不是ClaimsPrinciple.Current.Claims
。
From Introduction to Identity at docs.asp.net:
...在
HomeController.Index
操作方法中,您可以查看User.Claims
的详细信息。
Here is the relevant source code 来自 MVC 存储库:
public ClaimsPrincipal User
get
return HttpContext?.User;
【讨论】:
【参考方案3】:作为 ASP.NET Core 2.0 的一部分,您可以像上面描述的 Shaun 一样阅读 JWT 声明。如果您只是在寻找用户 ID(确保您已经使用“Sub”声明名称将其添加为声明的一部分),那么您可以根据您的用例使用以下两个示例来阅读:
读取用户 ID 声明:
public class AccountController : Controller
[Authorize]
[HttpGet]
public async Task<IActionResult> MethodName()
var userId = _userManager.GetUserId(HttpContext.User);
//...
return Ok();
阅读其他声明:
public class AccountController : Controller
[Authorize]
[HttpGet]
public async Task<IActionResult> MethodName()
var rolesClaim = HttpContext.User.Claims.Where( c => c.Type == ClaimsIdentity.DefaultRoleClaimType).FirstOrDefault();
//...
return Ok();
【讨论】:
【参考方案4】:使用此解决方案,您可以在使用 JWT 令牌时访问控制器中的 User.Identity
及其声明:
第一步:创建一个JwtTokenMiddleware:
public static class JwtTokenMiddleware
public static IApplicationBuilder UseJwtTokenMiddleware(
this IApplicationBuilder app,
string schema = "Bearer")
return app.Use((async (ctx, next) =>
IIdentity identity = ctx.User.Identity;
if (identity != null && !identity.IsAuthenticated)
AuthenticateResult authenticateResult = await ctx.AuthenticateAsync(schema);
if (authenticateResult.Succeeded && authenticateResult.Principal != null)
ctx.User = authenticateResult.Principal;
await next();
));
第 2 步:在 Startup.cs 中使用它:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
app.UseAuthentication();
app.UseJwtTokenMiddleware();
【讨论】:
很有帮助,虽然我不完全明白为什么。此外,您在那里令人费解的三元语句可以简化为identity != null && !identity.IsAuthenticated
以上是关于无法使用 ASP.NET Core 从 JWT 令牌获取声明的主要内容,如果未能解决你的问题,请参考以下文章
如何使用剃刀视图 ASP .Net Core 从 JWT 声明角色
将 Asp.Net Core 1 转换为 Core 2 后 Jwt 无法正常工作