简体   繁体   English

无法使用 ASP.NET Core 从 JWT 令牌中获取声明

[英]Can't get claims from JWT token with ASP.NET Core

I'm trying to do a really simple implementation of JWT bearer authentication with ASP.NET Core.我正在尝试使用 ASP.NET Core 做一个非常简单的 JWT 承载身份验证实现。 I return a response from a controller a bit like this:我从控制器返回一个响应,有点像这样:

    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())
       );

I have Jwt middleware for incoming requests:我有用于传入请求的 Jwt 中间件:

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
     AutomaticAuthenticate = true,
     AutomaticChallenge = true,
     TokenValidationParameters = tokenValidationParameters
});

This seems to work to protect resources with the authorize attribute, but the claims never show up.这似乎可以保护具有授权属性的资源,但声明从未出现。

    [Authorize]
    public async Task<IActionResult> Get()
    {
        var user = ClaimsPrincipal.Current.Claims; // Nothing here

You can't use ClaimsPricipal.Current in an ASP.NET Core application, as it's not set by the runtime.您不能在 ASP.NET Core 应用程序中使用ClaimsPricipal.Current ,因为它不是由运行时设置的。 You can read https://github.com/aspnet/Security/issues/322 for more information.您可以阅读https://github.com/aspnet/Security/issues/322了解更多信息。

Instead, consider using the User property, exposed by ControllerBase .相反,请考虑使用由ControllerBase公开的User属性。

Access User.Claims instead of ClaimsPrinciple.Current.Claims .访问User.Claims而不是ClaimsPrinciple.Current.Claims

From Introduction to Identity at docs.asp.net : 来自 docs.asp.net 的身份简介

...inside the HomeController.Index action method, you can view the User.Claims details. ...在HomeController.Index操作方法中,您可以查看User.Claims详细信息。

Here is the relevant source code from the MVC repository: 这是来自 MVC 存储库的相关源代码

public ClaimsPrincipal User
{
   get
   {
       return HttpContext?.User;
   }
}

As part of ASP.NET Core 2.0, you can read the JWT Claims like Shaun described above.作为 ASP.NET Core 2.0 的一部分,您可以像上述 Shaun 一样阅读 JWT 声明。 If you are only looking for the User Id (make sure you already add it as part of the claim using the "Sub" claim name) then you can use the following to two examples to read depending on your use case:如果您只是在寻找用户 ID(确保您已经使用“Sub”声明名称将其添加为声明的一部分),那么您可以根据您的用例使用以下两个示例来阅读:

Read User ID Claim:读取用户 ID 声明:

    public class AccountController : Controller
    {
        [Authorize]
        [HttpGet]
        public async Task<IActionResult> MethodName()
        {
            var userId = _userManager.GetUserId(HttpContext.User);
            //...
            return Ok();
        }
    }

Read Other Claims:阅读其他声明:

    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();
        }
    }

With this solution, you can access the User.Identity and its claims in controllers when you're using JWT tokens:使用此解决方案,您可以在使用 JWT 令牌时访问控制器中的User.Identity及其声明:

Step 1: create a JwtTokenMiddleware:第 1 步:创建一个 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 ? 1 : 0) : 1) != 0)
            {
                AuthenticateResult authenticateResult = await ctx.AuthenticateAsync(schema);
                if (authenticateResult.Succeeded && authenticateResult.Principal != null)
                    ctx.User = authenticateResult.Principal;
            }
            await next();
        }));
    }
}

Step 2: use it in Startup.cs:第二步:在Startup.cs中使用:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseAuthentication();
    app.UseJwtTokenMiddleware();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM