【问题标题】:JWT generation and validation in .net throws "Key is not supported".net 中的 JWT 生成和验证抛出“不支持密钥”
【发布时间】:2018-02-22 10:31:45
【问题描述】:

我正在使用以下代码生成和验证 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;
}

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

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

  • System.IdentityModel.Tokens.Jwt => 5.1.4
  • System.Security.Cryptography.Csp => 4.3.0

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

var token = tokenHandler.CreateToken(tokenDescriptor);

System.NotSupportedException: 'NotSupported_Method'

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

var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken securityToken);

Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: 'IDX10503: 签名验证失败。尝试的键:'Microsoft.IdentityModel.Tokens.RsaSecurityKey,KeyId: '。

【问题讨论】:

    标签: c# .net-core rsa jwt .net-standard


    【解决方案1】:

    我现在直接使用X509SecurityKey,而不是使用RsaSecurityKey。这适用于 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;
    }
    

    另外我只需要System.IdentityModel.Tokens.Jwt nuget 包,可以删除System.Security.Cryptography.Csp 包。

    【讨论】:

      【解决方案2】:

      谢谢你 NtFrex ..

      我只是对 NtFrex 的答案进行了一些小改动,以使其对我有用。 这也适用于 .net 4.5.1,我认为它可能对某人有所帮助。这是最终代码,但首先要创建一个证书。我已经使用 openssl 用 RSA512 创建了一个。

      创建令牌:

          private string GenerateToken1()
          {
              var tokenHandler = new JwtSecurityTokenHandler();
              var certificate = new X509Certificate2(@"C:\Users\myname\my-cert.pfx", "mypassword");
              var securityKey = new X509SecurityKey(certificate);
      
              var tokenDescriptor = new SecurityTokenDescriptor
              {
                  Subject = new ClaimsIdentity(),
                  Issuer = "Self",
                  IssuedAt = DateTime.Now,
                  Audience = "Others",
                  Expires = DateTime.Now.AddMinutes(30),
                  SigningCredentials = new SigningCredentials(
                      securityKey,
                      SecurityAlgorithms.RsaSha512Signature)
              };
      
              var token = tokenHandler.CreateToken(tokenDescriptor);
              return tokenHandler.WriteToken(token);
          }
      

      验证令牌:

          private bool ValidateToken1(string token)
          {
              var tokenHandler = new JwtSecurityTokenHandler();
              var certificate = new X509Certificate2(@"C:\Users\myname\my-cert.pfx", "mypassword");
              var securityKey = new X509SecurityKey(certificate);
      
              var validationParameters = new TokenValidationParameters
              {
                  ValidAudience = "Others",
                  ValidIssuer = "Self",
                  IssuerSigningKey = securityKey
              };
      
              SecurityToken securityToken;
              var principal = tokenHandler.ValidateToken(token, validationParameters, out securityToken);
              if (principal == null)
                  return false;
              if (securityToken == null)
                  return false;
      
              return true;
          }
      

      【讨论】:

      • 您可以使用 pfx 文件来验证令牌,但 pfx 文件包含私钥和公钥。您只需要公钥进行验证。 cer 文件是一个只包含公钥的容器。 Here 是如何将pfx 文件转换为cer 文件的简短说明。
      • 是的。谢谢你。这种方式可以在一个地方/应用程序生成令牌,也可以在多个地方/应用程序进行验证。这样您就可以将 .cer 文件提供给您信任的多个其他应用程序。身份提供者的种类创建它,服务提供者对其进行验证。我狂野的想象。谢谢你,拉克什
      猜你喜欢
      • 2014-07-23
      • 2014-10-14
      • 2016-12-04
      • 2017-10-15
      • 2015-07-05
      • 2019-04-04
      • 1970-01-01
      • 2020-05-15
      • 2011-08-25
      相关资源
      最近更新 更多