War*_* P 3 c# asp.net-identity json-web-token asp.net-core
使用 ASP.NET Core 1.0 (rtm),以及我生成的最小可验证示例,我发现我生成的 JSON Web 令牌没有通过 .net core json Web 令牌中间件声明挑战,并且因此失败错误:
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException:
IDX10504: Unable to validate signature, token does not have a signature:
'... ... token value here...'
Run Code Online (Sandbox Code Playgroud)
我制作了一个最小的示例,它在 ASP.NET Core RC1 中运行良好,但在 RTM 中不起作用。我没有移植到RC2上进行测试,但我相信这样的测试是没有意义的。您可以使用提供的测试脚本来练习演示:
python tests\testloginapi.py
GET OK: 200 http://localhost:54993/authorize/login?username=TEST&pas...
POST OK: 200 http://localhost:54993/authorize/login?username=TEST&pas...
authorization token received... eyJhbGciOi...
expected status 200 but got 401 for GET http://localhost:54993/authorizetest/test
Run Code Online (Sandbox Code Playgroud)
我的最小示例的要点是:
Startup.cs方法Configure有:
app.UseJwtBearerAuthentication(_keyArtifacts.getJwtBearerOptions());
Run Code Online (Sandbox Code Playgroud)
承载选项如下:
public static JwtBearerOptions CreateJwtBearerOption(RsaSecurityKey key, string tokenIssuer, string tokenAudience)
{
var jwtBearerOptions = new JwtBearerOptions();
jwtBearerOptions.AutomaticAuthenticate = true;
jwtBearerOptions.AutomaticChallenge = true;
jwtBearerOptions.TokenValidationParameters.ValidateIssuerSigningKey = true;
jwtBearerOptions.TokenValidationParameters.IssuerSigningKey = key;
jwtBearerOptions.TokenValidationParameters.ValidIssuer = tokenIssuer;
jwtBearerOptions.TokenValidationParameters.ValidateIssuer = true;
jwtBearerOptions.TokenValidationParameters.ValidateLifetime = true;
jwtBearerOptions.TokenValidationParameters.ClockSkew = TimeSpan.Zero;
jwtBearerOptions.TokenValidationParameters.ValidAudience = tokenAudience;
return jwtBearerOptions;
}
Run Code Online (Sandbox Code Playgroud)
这个问题实际上可以归结为:
在 Asp.net core 1.0 rtm 中,创建通过中间件挑战的令牌的最少步骤是什么?
我是否只是缺少一些简单的步骤(可能只有一行代码)来使这个演示工作,包括“签名”工作?
鉴于该演示仍然是一段可怕的代码,并且没有人应该在生产中使用它(因为我已经为此感到羞耻),我希望这个问题仍然能够阐明如何使系统UseJwtBearerAuthentication实际工作,至少在演示规模上是这样。
在 Asp.net core 1.0 rtm 中,创建通过中间件挑战的令牌的最少步骤是什么?我是否只是缺少一些简单的步骤(可能只有一行代码)来使这个演示工作,包括“签名”工作?
IdentityModel(负责验证 JWT 承载中间件收到的令牌的库)无法验证您的 JWT 令牌,因为它们实际上没有任何签名,如您所看到的错误中所述。
缺少签名可能是由于您SecurityTokenDescriptor.SigningCredentials在创建自己的令牌时没有分配而造成的:
JwtSecurityTokenHandler handler = BearerOptions
.SecurityTokenValidators
.OfType<JwtSecurityTokenHandler>()
.First();
var tokenData = new SecurityTokenDescriptor
{
Issuer = BearerOptions.TokenValidationParameters.ValidIssuer,
Audience = BearerOptions.TokenValidationParameters.ValidAudience,
Subject = new ClaimsIdentity(claims),
Expires = DateTime.Now.AddDays(1),
NotBefore = DateTime.Now
};
/*JwtSecurityToken*/
var securityToken =
handler.CreateToken
(
tokenData
);
Run Code Online (Sandbox Code Playgroud)
解决这个问题,它应该可以工作。
鉴于该演示仍然是一段可怕的代码,并且没有人应该在生产中使用它(因为我已经为它感到羞耻),我希望这个问题仍然能够阐明如何使 UseJwtBearerAuthentication 系统真正工作,至少在演示规模上是这样。
实际上,问题不在于如何使用 JWT 承载中间件,而在于如何生成自己的令牌。实现您自己的令牌发行者酱很好,但使用 OAuth 2.0 或 OpenID Connect 这样的标准通常更好且更易于使用(例如,当拥有 OIDC 服务器时,您不必配置 JWT 承载中间件,因为它会直接下载使用OIDC 发现的签名密钥)。
请随意阅读其他SO 答案以获取更多信息。