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

时间:2016-10-27 17:07:10

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

我试图用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

4 个答案:

答案 0 :(得分:15)

您不能在ASP.NET Core应用程序中使用ClaimsPricipal.Current,因为它不是由运行时设置的。您可以阅读https://github.com/aspnet/Security/issues/322了解更多信息。

相反,请考虑使用由User公开的ControllerBase属性。

答案 1 :(得分:9)

访问User.Claims而不是ClaimsPrinciple.Current.Claims

From Introduction to Identity at docs.asp.net

  

...在HomeController.Index操作方法中,您可以查看User.Claims详细信息。

来自MVC存储库的

Here is the relevant source code

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

答案 2 :(得分:3)

作为ASP.NET Core 2.0的一部分,您可以像上面描述的Shaun一样阅读JWT声明。如果您只是在寻找用户ID(请确保您已使用&#34; Sub&#34;声明名称将其添加为声明的一部分),那么您可以根据您的使用情况使用以下两个示例来阅读:

读取用户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();
        }
    }

答案 3 :(得分:1)

通过此解决方案,使用Jwt令牌时,您可以在控制器中访问User.Identiy及其声明:

  

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

第2步:在Startup.cs中使用它:

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