问题描述
好的,我正在努力将JWT发送到Web API,并且需要调试方面的帮助。我正在使用Angular 10客户端和ASP.NET Core 2.2作为服务器。我的身份验证流程如下:
向客户端发送的是在服务器中生成的令牌,如下所示:
Claim[] claims = new[] {
new Claim(JwtRegisteredClaimNames.Sub,user.Id),new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString()),new Claim(JwtRegisteredClaimNames.Iat,new DateTimeOffset(Now).ToUnixTimeSeconds().ToString())
// Todo: add additional claims here
};
int tokenExpirationMins = _configuration.GetValue<int>("Auth:JsonWebToken:TokenExpirationInMinutes");
SymmetricSecurityKey issuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Auth:JsonWebToken:Key"]));
JwtSecurityToken token = new JwtSecurityToken(
issuer: _configuration["Auth:JsonWebToken:Issuer"],audience: _configuration["Auth:JsonWebToken:Audience"],claims: claims,notBefore: Now,expires: Now.Add(TimeSpan.FromMinutes(tokenExpirationMins)),signingCredentials: new SigningCredentials( issuerSigningKey,SecurityAlgorithms.HmacSha256));
string encodedToken = new JwtSecurityTokenHandler().Writetoken(token);
// build & return the response
TokenResponseviewmodel response = new TokenResponseviewmodel()
{
Token = encodedToken,Expiration = tokenExpirationMins,Email = user.Email,User = user.UserName
};
return Json(response);
这很好,客户端从TokenResponseviewmodel
获取所有数据。
并且当客户端需要将API请求发送到我的api/user/test
端点时,该请求未经身份验证。请注意,这仅是我试用的机会。它是这样安全的:
/// <summary>
/// POST: api/user/test
/// </summary>
/// <returns>Status code.</returns>
[HttpGet("Test")]
[Authorize]
public IActionResult Gettest()
{
return new OkObjectResult(new { Message = "This is secure data!" });
}
并且由于该请求未通过API认证,因此它正在尝试重定向到http://localhost:50962/Account/Login?ReturnUrl=/api/user/test
:
目前,我不知道如何解决此问题。令牌似乎很好,但是被身份框架拒绝。 JWT未到期,因为到期时间设置为100min。
以下也是我的Angular请求调用:
executeCall(): void {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json','Authorization': 'bearer ' + this.auth.getAuth()!.token
})
};
console.log('executing call');
var url = 'http://localhost:50962/' + 'api/user/test';
this.http.get<string>(url,httpOptions)
.subscribe(
(val) => {
console.log("POST call successful value returned in body",val);
},response => {
console.log("POST call in error",response);
//todo: popup
},() => {
console.log("The POST observable is Now completed.");
//todo: popup
});
}
Startup.cs 身份验证设置:
services.AddAuthentication(opts =>
{
opts.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
opts.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(cfg =>
{
cfg.RequireHttpsMetadata = false;
cfg.Savetoken = true;
cfg.TokenValidationParameters = new TokenValidationParameters()
{
Validissuer = Configuration["Auth:Jwt:Issuer"],ValidAudience = Configuration["Auth:Jwt:Audience"],IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Auth:Jwt:Key"])),ClockSkew = TimeSpan.Zero,RequireExpirationTime = true,ValidateIssuer = true,ValidateIssuerSigningKey = true,ValidateAudience = true
};
})
应用设置配置:
"JsonWebToken": {
"Issuer": "http://localhost:50962/","Audience": "http://localhost:50962/","Key": "0pvUGXcvhg1ZRQZGBGy4","TokenExpirationInMinutes": 100
}
解决方法
问题出在这段代码上,我不得不将Authorize
替换为Authorize(AuthenticationSchemes = "Bearer")
:
/// <summary>
/// POST: api/user/test
/// </summary>
/// <returns>Status code.</returns>
[HttpGet("Test")]
[Authorize(AuthenticationSchemes = "Bearer")]
public IActionResult GetTest()
{
return new OkObjectResult(new { Message = "This is secure data!" });
}
基于this article。