C# ASP.net Core 2.0身份验证:ValidateSignature异常(IDX10503)
我试图验证使用.NETCore2.0和承载JWT令牌开发的API。但身份验证不起作用。为了更好地理解,我通过实现C# ASP.net Core 2.0身份验证:ValidateSignature异常(IDX10503),c#,authentication,asp.net-core-2.0,C#,Authentication,Asp.net Core 2.0,我试图验证使用.NETCore2.0和承载JWT令牌开发的API。但身份验证不起作用。为了更好地理解,我通过实现ISecurityTokenValidator创建了自己的验证器。例外情况如下- { Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: IDX10503: Signaturevalidationfailed.Keystried: 'Microsoft.IdentityModel.Tok
ISecurityTokenValidator
创建了自己的验证器。例外情况如下-
{
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException:
IDX10503: Signaturevalidationfailed.Keystried: 'Microsoft.IdentityModel.Tokens.SymmetricSecurityKey,
KeyId: Microsoft.IdentityModel.Tokens.SymmetricSecurityKey,
KeyId: '.Exceptionscaught: ''.token: '{
"alg": "HS256",
"typ": "JWT"
}.{
"iss": "TH_STS",
"aud": "http://sts-url.com/",
"nbf": 1111111111,
"exp": 2222222222,
"unique_name": "username",
"authmethod": "http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password",
"auth_time": "2018-05-14T15:31:19.64Z",
"user": "{
UserInfo: {
AccountId:1,
UserId:2
}
}",
"email": "username@email.com"
}'.
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(Stringtoken, TokenValidationParametersvalidationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(Stringtoken, TokenValidationParametersvalidationParameters, SecurityToken&validatedToken)
at Api.Security.CustomTokenValidator.ValidateToken(StringsecurityToken, TokenValidationParametersvalidationParameters, SecurityToken&validatedToken)inD: \Api\Security\CustomTokenValidator.cs: line 33
}
下面是我的验证器
public class CustomTokenValidator : ISecurityTokenValidator
{
public bool CanReadToken(string securityToken)
{
try
{
var jwtToken = new JwtSecurityTokenHandler().ReadToken(securityToken);
return jwtToken != null && jwtToken.ValidTo >= DateTime.UtcNow;
}
catch (SecurityTokenValidationException ex)
{
return false;
}
catch (Exception ex)
{
return false;
}
}
public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters,
out SecurityToken validatedToken)
{
var handler = new JwtSecurityTokenHandler();
try
{
return handler.ValidateToken(securityToken, validationParameters, out validatedToken);
}
catch (Exception ex)
{
}
validatedToken = null;
return null;
}
public bool CanValidateToken { get; }
public int MaximumTokenSizeInBytes { get; set; }
}
以下是启动的代码
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
SetupAuthentication(services);
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
.Build());
});
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
app.UseCors("CorsPolicy");
}
private void SetupAuthentication(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(UpdateJwtBearerOptions);
}
private void UpdateJwtBearerOptions(JwtBearerOptions options)
{
options.RequireHttpsMetadata = false;
options.SecurityTokenValidators.Add(new CustomTokenValidator());
options.TokenValidationParameters = GetTokenValidationParameters();
}
private TokenValidationParameters GetTokenValidationParameters()
{
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
};
var token1 = ReadToken1();
var token2 = ReadToken2();
tokenValidationParameters.ValidIssuers = new List<string> { token1.Issuer, token2.Issuer };
tokenValidationParameters.ValidAudiences = new List<string> { token1.Audience, token2.Audience };
tokenValidationParameters.IssuerSigningKeys = new List<SecurityKey> { GetIssuerSigningKey(token1), GetIssuerSigningKey(token2) };
return tokenValidationParameters;
}
private static SymmetricSecurityKey GetIssuerSigningKey(IdentityToken token)
{
return new SymmetricSecurityKey(Encoding.UTF8.GetBytes(token.Key));
}
private IdentityToken ReadToken1()
{
return new IdentityToken
{
Audience = Configuration["IdentityToken:AudienceUris:0"],
Issuer = Configuration["IdentityToken:Issuers:0:Issuer"],
Key = Configuration["IdentityToken:Issuers:0:SymmetricKey"]
};
}
private IdentityToken ReadToken2()
{
return new IdentityToken
{
Audience = Configuration["IdentityToken:AudienceUris:1"],
Issuer = Configuration["IdentityToken:Issuers:1:Issuer"],
Key = Configuration["IdentityToken:Issuers:1:SymmetricKey"]
};
}
}
public class IdentityToken
{
public string Issuer { get; set; }
public string Audience { get; set; }
public string Key { get; set; }
}
公共类启动
{
公共启动(IConfiguration配置)
{
配置=配置;
}
公共IConfiguration配置{get;}
public void配置服务(IServiceCollection服务)
{
认证(服务);
services.AddCors(选项=>
{
options.AddPolicy(“CorsPolicy”,
builder=>builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
.Build());
});
services.AddMvc();
}
公共无效配置(IApplicationBuilder应用程序,IHostingEnvironment环境)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
附录UseCors(“公司政策”);
}
私有身份验证(IServiceCollection服务)
{
services.AddAuthentication(选项=>
{
options.DefaultAuthenticateScheme=JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme=JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(更新jwtbeareroptions);
}
私有void UpdateJwtBearerOptions(JwtBearerOptions选项)
{
options.RequireHttpsMetadata=false;
options.SecurityTokenValidators.Add(新的CustomTokenValidator());
options.TokenValidationParameters=GetTokenValidationParameters();
}
私有令牌验证参数GetTokenValidationParameters()
{
var tokenValidationParameters=新的tokenValidationParameters
{
validateisuer=true,
ValidateAudience=true,
ValidateSuersigningKey=true,
ValidateLifetime=true,
};
var token1=ReadToken1();
var token2=ReadToken2();
tokenValidationParameters.ValidIssuers=新列表{token1.Issuer,token2.Issuer};
tokenValidationParameters.Validudiences=新列表{token1.Audience,token2.Audience};
tokenValidationParameters.IssuerSigningKeys=新列表{GetIssuerSigningKey(token1),GetIssuerSigningKey(token2)};
返回tokenValidationParameters;
}
私有静态对称安全密钥GetIssuerSigningKey(IdentityToken令牌)
{
返回新的SymmetricSecurityKey(Encoding.UTF8.GetBytes(token.Key));
}
私有标识Token ReadToken1()
{
返回新的IdentityToken
{
受众=配置[“识别对象:AudienceUris:0”],
发卡机构=配置[“IdentityToken:发卡机构:0:发卡机构”],
Key=Configuration[“IdentityToken:Issuers:0:SymmetricKey”]
};
}
私有标识Token ReadToken2()
{
返回新的IdentityToken
{
受众=配置[“识别对象:AudienceUris:1”],
发卡机构=配置[“IdentityToken:发卡机构:1:发卡机构”],
Key=Configuration[“IdentityToken:Issuers:1:SymmetricKey”]
};
}
}
公共类标识
{
公共字符串颁发者{get;set;}
公共字符串访问群体{get;set;}
公共字符串密钥{get;set;}
}
当前MVC应用程序的配置如下
<system.identityModel>
<identityConfiguration saveBootstrapContext="true">
<audienceUris>
<add value="http://url1.com/" />
<add value="http://url2.com/" />
</audienceUris>
<securityTokenHandlers>
<add type="System.IdentityModel.Tokens.JwtSecurityTokenHandler, System.IdentityModel.Tokens.Jwt, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<add type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089">
<sessionTokenRequirement lifetime="00:30:00"></sessionTokenRequirement>
</add>
<securityTokenHandlerConfiguration>
<issuerTokenResolver type="System.IdentityModel.Tokens.NamedKeyIssuerTokenResolver, System.IdentityModel.Tokens.JWT">
<securityKey symmetricKey="key0" name="TH_STS" />
<securityKey symmetricKey="key1" name="http://sts-url.com" />
</issuerTokenResolver>
<issuerNameRegistry type="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<authority name="TH_STS">
<keys>
<add symmetricKey="key0" />
</keys>
<validIssuers>
<add name="TH_STS" />
</validIssuers>
</authority>
<authority name="http://sts-url.com">
<keys>
<add symmetricKey="key1" />
</keys>
<validIssuers>
<add name="http://sts-url.com" />
</validIssuers>
</authority>
</issuerNameRegistry>
</securityTokenHandlerConfiguration>
</securityTokenHandlers>
</identityConfiguration>
</system.identityModel>
bool Validate(string token, out IList<ClaimsIdentity> validatedIdentity)
{
try
{
var handlers = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.SecurityTokenHandlers;
var jwtToken = handlers.ReadToken(token) as JwtSecurityToken;
if (jwtToken == null || jwtToken.ValidTo < DateTime.UtcNow)
{
validatedIdentity = null;
return false;
}
validatedIdentity = handlers.ValidateToken(jwtToken);
return true;
}
catch (SecurityTokenValidationException ex)
{
validatedIdentity = null;
return false;
}
catch (Exception ex)
{
validatedIdentity = null;
return false;
}
}
代码如下
<system.identityModel>
<identityConfiguration saveBootstrapContext="true">
<audienceUris>
<add value="http://url1.com/" />
<add value="http://url2.com/" />
</audienceUris>
<securityTokenHandlers>
<add type="System.IdentityModel.Tokens.JwtSecurityTokenHandler, System.IdentityModel.Tokens.Jwt, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<add type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089">
<sessionTokenRequirement lifetime="00:30:00"></sessionTokenRequirement>
</add>
<securityTokenHandlerConfiguration>
<issuerTokenResolver type="System.IdentityModel.Tokens.NamedKeyIssuerTokenResolver, System.IdentityModel.Tokens.JWT">
<securityKey symmetricKey="key0" name="TH_STS" />
<securityKey symmetricKey="key1" name="http://sts-url.com" />
</issuerTokenResolver>
<issuerNameRegistry type="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<authority name="TH_STS">
<keys>
<add symmetricKey="key0" />
</keys>
<validIssuers>
<add name="TH_STS" />
</validIssuers>
</authority>
<authority name="http://sts-url.com">
<keys>
<add symmetricKey="key1" />
</keys>
<validIssuers>
<add name="http://sts-url.com" />
</validIssuers>
</authority>
</issuerNameRegistry>
</securityTokenHandlerConfiguration>
</securityTokenHandlers>
</identityConfiguration>
</system.identityModel>
bool Validate(string token, out IList<ClaimsIdentity> validatedIdentity)
{
try
{
var handlers = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.SecurityTokenHandlers;
var jwtToken = handlers.ReadToken(token) as JwtSecurityToken;
if (jwtToken == null || jwtToken.ValidTo < DateTime.UtcNow)
{
validatedIdentity = null;
return false;
}
validatedIdentity = handlers.ValidateToken(jwtToken);
return true;
}
catch (SecurityTokenValidationException ex)
{
validatedIdentity = null;
return false;
}
catch (Exception ex)
{
validatedIdentity = null;
return false;
}
}
bool-Validate(字符串标记,out-IList-validatedIdentity)
{
尝试
{
var handlers=FederatedAuthentication.FederationConfiguration.IdentityConfiguration.SecurityTokenHandlers;
var jwtToken=handlers.ReadToken(token)作为JwtSecurityToken;
if(jwtToken==null | | jwtToken.ValidTo
我不知道我错过了什么。他们在我的代码中有任何配置问题吗?异常说明它无法验证JWT令牌的
签名
,但它可以读取标题
和有效负载
。代码使用config提供的对称密钥验证签名
在旧配置中,issuertokensolver
是System.IdentityModel.Tokens.namedKeyissuertokensolver
。从中,可以发现它正在使用Convert.FromBase64String(value)
读取对称密钥
在dot.netcore2.0中,我使用了newsymmetricsecuritykey(Encoding.UTF8.GetBytes(token.Key))
读取密钥
将其更改为