C# ASP.net Core 2.0身份验证:ValidateSignature异常(IDX10503)

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

我试图验证使用.NETCore2.0和承载JWT令牌开发的API。但身份验证不起作用。为了更好地理解,我通过实现
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))
读取密钥

将其更改为