我已经构建了一个在ASP.NET Core中使用JWT承载认证的应用程序。在进行身份验证时,我定义了一些我需要在另一个WebAPI控制器中读取的自定义声明,以便执行某些操作。
任何想法我如何实现这一目标?
我的代码如下所示:(代码已简化)
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);
.................
}
另一个控制器:(需要阅读&#34; verificationKey&#34;声明。)
[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();
}
}
答案 0 :(得分:22)
您应该能够在控制器中检索此类声明
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
值。
答案 1 :(得分:1)
// 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...
答案 2 :(得分:0)
.NET Framework有一些JWT实现。如果您使用 System.IdentityModel.Tokens.Jwt ,则在验证令牌时,您会获得一个 System.Security.Claims.ClaimsPrincipal ,用于存储令牌的声明。它的声明&#34;属性。因此,您可以获得令牌的声明如下:
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/是此实现的一个很好的示例。
答案 3 :(得分:0)
在网络核心2中通过JwtBearerDefaults方案进行授权的任何控制器中,您可以使用:
[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();
}