【问题标题】:JWT validation works in .NET Core, fails in .NET FrameworkJWT 验证在 .NET Core 中有效,在 .NET Framework 中失败
【发布时间】:2019-09-05 05:47:37
【问题描述】:

与here 提到的问题类似,我遇到了一个问题,即 JWT 验证在 .NET Core 2.2(macOS 和 Windows)上运行时有效,但无法在 .NET Framework 4.7.2 上运行;在那里,它抛出一个异常:

Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException:'IDX10503:签名验证失败。尝试的键:'Microsoft.IdentityModel.Tokens.RsaSecurityKey,KeyId: '。 捕获的异常: ''。 令牌:'{"typ":"JWT","alg":"RS256"}.{"sub":"username","scope":"examplescope","roles":["examplerole"],"iss ":"https://example.com/","exp":1556788122,"iat":1555316893}'.'
在 System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters) 在 C:\agent1_work\109\s\src\System.IdentityModel.Tokens.Jwt\JwtSecurityTokenHandler.cs:line 979
在 C:\agent1_work\109\s\src\System.IdentityModel.Tokens.Jwt\JwtSecurityTokenHandler.cs:line 722 中的 System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& encryptedToken)
在 C:\Users\User\source\repos\JWTTest\JWTTestCore\Program.cs: 35 行中的 JWTTest.Program.Main(String[] args) 处

测试程序:

using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using Microsoft.IdentityModel.Logging;
using Microsoft.IdentityModel.Tokens;

namespace JWTTest {
    class Program {
        static void Main(string[] args) {
            // Validation parameters
            //var rsa = new RSACryptoServiceProvider(); // this works in .NET Core on macOS but not on Windows ...
            var rsa = RSA.Create();
            rsa.KeySize = 2048;
            rsa.ImportParameters(new RSAParameters {
                  Modulus = Convert.FromBase64String("AM/Nh9cX8U+8ZeOcKyodBcZun1dgQysFZWLplOof9SpHt45vmh7gy3FxhLQEj2NrhV44AiymRxr1mmZ7K9K105MfDe/QAAFBy715/NHmKZxH7QvypiiPMf2jwpb+n/Ss0oUZ68zPSfO9aZwhUBWO+J7NBnWEwoq3Bxda5IQPMRkMohD5VZ0IPvUotcg6k7cOoRamvOiDyVQ58uVx+Wd+vucdVo6uT/kMKlBZoahU/hnREfNZojf0lAkzcxOlZcKbms/+Mu8vb/jeZSGYZpykL0c3ohGJ49NteFIXggx8AH6E8ROpijq2NeA7AK3Y+33LEJmSwOdNnZ1ZaY515AqeN/S+ay4Ra15V91qdu4ph1B+G5aKV3rcu0v1Y6/eG5dgHPIBRaf7sGVG7rCDOgrfbjaEdNvqX1TgNnmfogZElFt2qs5VVWKE5zEuOEkOngTEuvlJAsTgh/Uw/OS7vinbSmtGXFhKS2teatITyuNALaPeFAdA9qz9c90IJs9vbf9Uf9FFWvfrer9lhDhLUuehKJTt8vBtoqea46nf3IGthLeiGQmrVSEytoTGW67gGpVo8Xd+iat5ilhciNWX1/rscv66cg0S1IK7A/oXqWJO/WNq6EzFxI/f/0klMrcC8M5qioiiwNMvpAj/6KDZSxoII+rS9RDz/E0xWprkErrIa7aVv"),
                  Exponent = Convert.FromBase64String("AQAB")
            });
            var validationParameters = new TokenValidationParameters {
                ClockSkew = TimeSpan.FromMinutes(1),
                ValidateAudience = false,
                ValidateIssuer = true,
                ValidIssuer = "https://example.com/",
                IssuerSigningKey = new RsaSecurityKey(rsa)
            };

            // Verify token
            IdentityModelEventSource.ShowPII = true;
            JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
            var token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VybmFtZSIsInNjb3BlIjoiZXhhbXBsZXNjb3BlIiwicm9sZXMiOlsiZXhhbXBsZXJvbGUiXSwiaXNzIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS8iLCJleHAiOjE1NTY3ODgxMjIsImlhdCI6MTU1NTMxNjg5M30.XHowlwvKX73I2KqKFInaadAGZNtj7UVvjh1EuodnttlUOmC59Q6XPSwrKkATLqicl46c7ItYGl75Mj5PVy03tOXXlxgsgoP81t1WM08QeHlrbPvay1aSFqcj7JcnX6fu9qiXzRhhh2XYw5UrT8-R3kIQMQA7d4cnT6Z1oeoHzV38ywi3rv3BapwuFtrFmSXHHsQMcTUK_Whf-5CEPj6O9CEdCXKFh05McGZDBoYBgZpn7d2H2EJNV9KhsasafsD7TVs6w3myOfc3HaqtHhFDUmpzwmWZdzn-i0zSxz1qussd9ovDaf03zkd7OWtau9_44T1KkWVK8GlAxuXnuPmCuh76ELQjpNqQerRL-F4EYkUwUJEQHFf2IolpCx4i2pDkzyax-fL4ZwjsncWNUJdXyex3Pk-OcSD11lJl0UWRE5gh-pOeEd1Ybhxu4z42Vet1rAM3VWXXyJQzAz2diVTJIbvaG3uq4-HxoBTkvfpXLj_2RN_oSTkyD8JoBIHQtMT1h7eZhHbxFLsxLoGNQVWJmyU_BPCs282m41n2Jd4ezR1M1XlLUixk8v1M1Rjxg3s7c8Q_PezmXzv3IrK8ftrmfb73uBwTxJukOeFk3yC7e7ZLhYJsBlJsyeGfJF8ayNSjxwkrXJN3JVZMOzZCQNnl3zc8AL6gjloFFlhgB5nlxJU";
            // exception is thrown on the next line:
            var user = handler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);

            foreach (var role in user.Claims.Where(c => c.Type == ClaimTypes.Role)) {
                Console.WriteLine("Role: " + role.Value);
            }
        }
    }
}

JWT 是使用this Java library 生成的,但我不确定这是否重要;根据jwt.io 是有效的。 (链接显示签名无效,但这是网站中的一个错误;只需在公钥末尾添加一个换行符即可触发验证。)我尝试了由 RS256 和 RS512 算法生成的令牌,但这并没有区别。

我不确定它是否取决于 Visual Studio 设置;

  • macOS Mojave 10.14.4; Visual Studio for Mac 7.7.3(内部版本 43); .NET Core SDK 版本 2.2.105(有效)
  • Windows 10,版本 1809; Visual Studio 2017,v15.9.11
    • .NET Core SDK 2.2.106(有效)
    • .NET Framework 4.7.2 (不起作用)

【问题讨论】:

  • 我不确定,但我注意到一件事:Convert.FromBase64String("AM/Nh9cX8...") 是byte[513],应该是byte[512]?
  • 我也不确定,但这是问题的简化版本。实际上,我使用的是this library,它根据OIDC discovery document 检索签名密钥。
  • 试试这个...答案声称可以在 Windows 和 linux 中工作,并且可能是您的问题的解决方案stackoverflow.com/questions/54585148/…
  • 谢谢!我在做研究时看到了这个问题。事实证明,它修复了 Windows 上的 .NET Core 问题,但不幸的是 .NET Framework 问题仍然存在 :(

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


【解决方案1】:

不,Java 库不应该是问题所在。您附加的同一链接中提到了该问题。您需要覆盖并使用自定义密钥验证,因为库中的 RSA 解密附加了某种错误。

查看this 和this 了解更多信息[再次与您附加的相同链接]。

该问题被引用到另一个问题中并且已关闭。可能它应该被修复,除非某些包没有更新或没有更新或在那里提到的版本。

【讨论】:

  • 事实证明你是对的(我应该听过@vasily.sib 的评论)——这是导致问题的空字节。解决方案 here 对我有用(当然,我的密钥是原来的两倍)。
猜你喜欢
  • 1970-01-01
  • 2018-04-27
  • 2017-06-22
  • 2021-06-27
  • 2019-06-24
  • 2017-04-05
  • 2010-10-11
  • 2018-03-13
  • 2020-05-18
相关资源
最近更新 更多