繁体   English   中英

从 WebAPI Controller - JWT 令牌获取声明,

[英]Get claims from a WebAPI Controller - JWT Token,

我在 ASP.NET Core 中构建了一个使用 JWT 承载身份验证的应用程序。 进行身份验证时,我定义了一些自定义声明,我需要在另一个 WebAPI controller 中阅读这些声明才能执行某些操作。

任何想法我怎样才能做到这一点?

这就是我的代码的样子:(代码已被简化)

public async Task<IActionResult> AuthenticateAsync([FromBody] UserModel user)
    {
        ..............

                var tokenHandler = new JwtSecurityTokenHandler();
                var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
                var tokenDescriptor = new SecurityTokenDescriptor
                {
                    Subject = new ClaimsIdentity(new Claim[]
                    {
                        new Claim("userSecurityKey", userDeserialized.SecurityKey.ToString()),
                        new Claim("timeStamp",timeStamp),
                        new Claim("verificationKey",userDeserialized.VerificationKey.ToString())

                    }),
                    Expires = DateTime.UtcNow.AddDays(7),
                    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),
                        SecurityAlgorithms.HmacSha256Signature)
                };
                var token = tokenHandler.CreateToken(tokenDescriptor);
                var tokenString = tokenHandler.WriteToken(token);

     .................                           

    }

另一个 controller:(它需要读取“verificationKey”声明。)

    [HttpGet]
    [Route("getcandidate")]
    public async Task<IActionResult> GetCandidateAsync()
    {

        try
        {
             ............    


            var verificationKey = //TODO: GET VerificationKey FROM THE TOKEN

            var verificationRecord = await service.GetVerificationRecordAsync(verificationKey);

            .................

        }
        catch (Exception)
        {
            return NotFound();
        }
    }

您应该能够在控制器中检索此类声明

var identity = HttpContext.User.Identity as ClaimsIdentity;
if (identity != null)
{
    IEnumerable<Claim> claims = identity.Claims; 
    // or
    identity.FindFirst("ClaimName").Value;

}

如果您愿意,您可以为IPrincipal接口编写扩展方法并使用上面的代码检索声明,然后使用(例如)检索它们

HttpContext.User.Identity.MethodName();

为了完整的答案。 要解码JWT令牌,让我们编写一个方法来验证令牌并提取信息。

public static ClaimsPrincipal ValidateToken(string jwtToken)
    {
        IdentityModelEventSource.ShowPII = true;

        SecurityToken validatedToken;
        TokenValidationParameters validationParameters = new TokenValidationParameters();

        validationParameters.ValidateLifetime = true;

        validationParameters.ValidAudience = _audience.ToLower();
        validationParameters.ValidIssuer = _issuer.ToLower();
        validationParameters.IssuerSigningKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.UTF8.GetBytes(_appSettings.Secret));

        ClaimsPrincipal principal = new JwtSecurityTokenHandler().ValidateToken(jwtToken, validationParameters, out validatedToken);


        return principal;
    }

现在我们可以使用以下方法验证和提取声明:

ValidateToken(tokenString)?.FindFirst("ClaimName")?.Value

您应该注意,如果验证失败,ValidateToken方法将返回null值。

在任何通过 JwtBearerDefaults 方案授权的 controller from.net core 2 中,您可以使用:

 [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
 public ActionResult Index()
    {
        var user = User.FindFirst("Name").Value;
        //or if u want the list of claims
        var claims = User.Claims;

        return View();
    }

解码 JWT 并获得声明的一种方法是使用System.IdentityModel.Tokens

public string getJWTTokenClaim(string token, string claimName)
{
    try
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var securityToken = (JwtSecurityToken)tokenHandler.ReadToken(token);
        var claimValue = securityToken.Claims.FirstOrDefault(c => c.Type == claimName)?.Value;
        return claimValue;
    }
    catch (Exception)
    {
        //TODO: Logger.Error
        return null;
    }
}
// Cast to ClaimsIdentity.
var identity = HttpContext.User.Identity as ClaimsIdentity;

// Gets list of claims.
IEnumerable<Claim> claim = identity.Claims; 

// Gets name from claims. Generally it's an email address.
var usernameClaim = claim
    .Where(x => x.Type == ClaimTypes.Name)
    .FirstOrDefault();

// Finds user.
var userName = await _userManager
    .FindByNameAsync(usernameClaim.Value);

if (userName == null)
{
    return BadRequest();
}

// The rest of your code goes here...

.NET Framework有一些JWT实现。 如果您使用System.IdentityModel.Tokens.Jwt ,则在验证令牌时,您将获得一个System.Security.Claims.ClaimsPrincipal ,用于将令牌的声明存储在其“Claims”属性中。 因此,您可以获得令牌的声明,如下所示:

        string token = // ... read the token
        JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
        TokenValidationParameters validationParameters = ...;
        SecurityToken securityToken;
        IPrincipal principal;
        try
        {
            // token validation
            principal = tokenHandler.ValidateToken(token, validationParameters, out securityToken);
            // Reading the "verificationKey" claim value:
            var vk = principal.Claims.SingleOrDefault(c => c.Type == "verificationKey").Value; 
        }
        catch
        {
            principal = null; // token validation error
        }

现在你在哪里放置这段代码? 我的选择是将令牌验证实现为从AuthorizationFilterAttribute派生的授权过滤器属性。 如果使用该属性修饰控制器,则在每次调用控制器端点之前执行其OnAuthorization方法。 将上述代码放在OnAuthorization方法上,并将令牌验证返回的主体存储在HttpContext.Current.User上 ,也可以在API上的任何端点上访问。 http://blogs.quovantis.com/json-web-token-jwt-with-web-api/是此实现的一个很好的示例。

暂无
暂无

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

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