.net 中的 JWT 生成和验证抛出“不支持密钥”

NtF*_*reX 3 c# rsa jwt .net-core .net-standard

我使用以下代码生成并验证 JWT。

static string GenerateToken()
{
    var tokenHandler = new JwtSecurityTokenHandler();
    var certificate = new X509Certificate2(@"Test.pfx", "123");
    var rsa = certificate.GetRSAPrivateKey();

    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(),
        Issuer = "Self",
        IssuedAt = DateTime.Now,
        Audience = "Others",
        Expires = DateTime.MaxValue,
        SigningCredentials = new SigningCredentials(
            new RsaSecurityKey(rsa),
            SecurityAlgorithms.RsaSha256Signature)
    };

    var token = tokenHandler.CreateToken(tokenDescriptor);
    return tokenHandler.WriteToken(token);
}

static bool ValidateToken(string token)
{
    var tokenHandler = new JwtSecurityTokenHandler();
    var certificate = new X509Certificate2(@"Test.cer");
    var rsa = certificate.GetRSAPublicKey();

    var validationParameters = new TokenValidationParameters
    {
        ValidAudience = "Others",
        ValidIssuer = "Self",
        IssuerSigningKey = new RsaSecurityKey(rsa)
    };

    var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
    if (principal == null)
        return false;
    if (securityToken == null)
        return false;

    return true;
}
Run Code Online (Sandbox Code Playgroud)

我在一个针对 .net standard 2.0 和 net46 的库中有这段代码。

当我在 .net core app 2.0 项目中使用该库时,一切都按预期工作。我使用以下 nuget 包。

  • System.IdentityModel.Tokens.Jwt => 5.1.4
  • 系统.安全.加密.Csp => 4.3.0

但是当我使用 .net46 构建相同的代码时,在尝试生成令牌时出现以下异常。

var token = tokenHandler.CreateToken(tokenDescriptor);
Run Code Online (Sandbox Code Playgroud)

System.NotSupportedException:“NotSupported_Method”

当我尝试验证令牌时,会引发以下异常。

var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
Run Code Online (Sandbox Code Playgroud)

Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException:'IDX10503:签名验证失败。尝试过的密钥:“Microsoft.IdentityModel.Tokens.RsaSecurityKey,KeyId:”。

NtF*_*reX 5

我没有使用 an,而是RsaSecurityKey直接使用X509SecurityKeynow。这适用于 netstandard2.0 和 net46。

static string GenerateToken()
{
    var tokenHandler = new JwtSecurityTokenHandler();
    var certificate = new X509Certificate2(@"Test.pfx", "123");
    var securityKey = new X509SecurityKey(certificate);

    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(),
        Issuer = "Self",
        IssuedAt = DateTime.Now,
        Audience = "Others",
        Expires = DateTime.MaxValue,
        SigningCredentials = new SigningCredentials(
            securityKey,
            SecurityAlgorithms.RsaSha256Signature)
    };

    var token = tokenHandler.CreateToken(tokenDescriptor);
    return tokenHandler.WriteToken(token);
}

static bool ValidateToken(string token)
{
    var tokenHandler = new JwtSecurityTokenHandler();
    var certificate = new X509Certificate2(@"Test.cer");
    var securityKey = new X509SecurityKey(certificate);

    var validationParameters = new TokenValidationParameters
    {
        ValidAudience = "Others",
        ValidIssuer = "Self",
        IssuerSigningKey = securityKey
    };

    var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
    if (principal == null)
        return false;
    if (securityToken == null)
        return false;

    return true;
}
Run Code Online (Sandbox Code Playgroud)

另外我只需要System.IdentityModel.Tokens.Jwtnuget 包并且可以删除该System.Security.Cryptography.Csp包。