【问题标题】:Can't get claims from JWT token with ASP.NET Core无法使用 ASP.NET Core 从 JWT 令牌获取声明
【发布时间】:2023-03-23 23:35:01
【问题描述】:

我正在尝试使用 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吗?

标签: c# asp.net-core jwt claims-based-identity


【解决方案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 &amp;&amp; !identity.IsAuthenticated
        猜你喜欢
        • 2018-06-16
        • 2020-01-17
        • 1970-01-01
        • 1970-01-01
        • 2022-07-08
        • 2019-06-22
        • 2016-12-23
        • 2018-07-01
        • 2023-02-14
        相关资源
        最近更新 更多