Son*_*Sam 4 c# oauth-2.0 asp.net-core
应用程序重新启动或发布后,我收到以下带有有效令牌的错误
IDX10503: Signature validation failed. Keys tried: 'System.IdentityModel.Tokens.RsaSecurityKey
Exceptions caught:
token: '{"typ":"JWT","alg":"RS256","kid":null}.{"unique_name":"test@test.com","iss":"XXXXXX","aud":"XXXXX","exp":1444876186}'
Run Code Online (Sandbox Code Playgroud)
这是生成KEY的函数
private void generateRsaKeys()
{
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048))
{
key = new RsaSecurityKey(rsa.ExportParameters(true));
credentials = new SigningCredentials (key,SecurityAlgorithms.RsaSha256Signature, SecurityAlgorithms.Sha256Digest);
rsa.PersistKeyInCsp = true;
}
}
Run Code Online (Sandbox Code Playgroud)
这就是配置的完成方式
services.ConfigureOAuthBearerAuthentication(options =>
{
options.AutomaticAuthentication = true;
options.TokenValidationParameters.IssuerSigningKey = generateRsaKeys();
options.TokenValidationParameters.ValidAudience = audience;
options.TokenValidationParameters.ValidIssuer = issuer;
});
app.UseStaticFiles();
app.UseOAuthBearerAuthentication();
// Add MVC to the request pipeline.
app.UseMvc();
Run Code Online (Sandbox Code Playgroud)
这是我的控制器上的操作
// POST: /token
[HttpPost()]
public async Task<IActionResult> Token([FromBody] LoginModel model)
{
if (!ModelState.IsValid)
return HttpBadRequest();
JwtSecurityTokenHandler handler = _bearerOptions.SecurityTokenValidators.OfType<JwtSecurityTokenHandler>().First();
try
{
var user = await _Repo.GetDetailAsync(model.Email);
if (!model.Password.Equals(user.Password))
return HttpUnauthorized();
JwtSecurityToken securityToken = handler.CreateToken
(
issuer: _bearerOptions.TokenValidationParameters.ValidIssuer,
audience: _bearerOptions.TokenValidationParameters.ValidAudience,
signingCredentials: _signingCredentials,
subject: new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, user.Email) }),
expires: DateTime.Now.AddMinutes(2)
);
string token = handler.WriteToken(securityToken);
return new ObjectResult(new TokenModel() { AccessToken = token, TokenType = "bearer" });
}
catch (Exception ex)
{
// TODO: add loggin logic here
return HttpUnauthorized();
}
}
Run Code Online (Sandbox Code Playgroud)
如果您每次(重新)启动服务器时都会生成新的 RSA 密钥,那么这并不奇怪:KEY A无法使用 验证签名的令牌KEY B。为了使您的方案发挥作用,您需要将 RSA 密钥存储在某处,并在启动期间使用相同的密钥。
一种方法是在某处调用rsa.ExportParameters(true)和存储不同的参数,以便您可以使用 轻松检索和导入它们rsa.ImportParameters(...)。
但您最好的选择是使用AspNet.Security.OpenIdConnect.Server,它将在最新版本中自动为您生成并存储 RSA 密钥:
public class Startup {
public void ConfigureServices(IServiceCollection services) {
services.AddAuthentication();
services.AddCaching();
}
public void Configure(IApplicationBuilder app) {
// Add a new middleware validating access tokens issued by the OIDC server.
app.UseJwtBearerAuthentication(options => {
options.AutomaticAuthentication = true;
options.Authority = "resource_server_1";
options.RequireHttpsMetadata = false;
});
// Add a new middleware issuing tokens.
app.UseOpenIdConnectServer(options => {
options.AllowInsecureHttp = true;
options.Provider = new OpenIdConnectServerProvider {
// Override OnValidateClientAuthentication to skip client authentication.
OnValidateClientAuthentication = context => {
// Call Skipped() since JS applications cannot keep their credentials secret.
context.Skipped();
return Task.FromResult<object>(null);
},
// Override OnGrantResourceOwnerCredentials to support grant_type=password.
OnGrantResourceOwnerCredentials = context => {
// Do your credentials validation here.
// Note: you can call Rejected() with a message
// to indicate that authentication failed.
var identity = new ClaimsIdentity(OpenIdConnectDefaults.AuthenticationScheme);
identity.AddClaim(ClaimTypes.NameIdentifier, "todo");
// By default, claims are not serialized in the access and identity tokens.
// Use the overload taking a "destination" to make sure your claims
// are correctly inserted in the appropriate tokens.
identity.AddClaim("urn:customclaim", "value", "token id_token");
var ticket = new AuthenticationTicket(
new ClaimsPrincipal(identity),
new AuthenticationProperties(),
context.Options.AuthenticationScheme);
// Call SetResources with the list of resource servers
// the access token should be issued for.
ticket.SetResources(new[] { "resource_server_1" });
// Call SetScopes with the list of scopes you want to grant
// (specify offline_access to issue a refresh token).
ticket.SetScopes(new[] { "profile", "offline_access" });
context.Validated(ticket);
return Task.FromResult<object>(null);
}
}
});
app.UseMvc();
}
}
Run Code Online (Sandbox Code Playgroud)
{
"dependencies": {
"Microsoft.AspNet.Server.WebListener": "1.0.0-rc1-final",
"Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
"Microsoft.AspNet.Authentication.JwtBearer": "1.0.0-rc1-final",
"AspNet.Security.OpenIdConnect.Server": "1.0.0-beta4"
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
19799 次 |
| 最近记录: |