【发布时间】:2022-01-26 19:18:09
【问题描述】:
首先是一些代码...我有一个安全类:
public static class Security
{
public static RSACryptoServiceProvider RSA { get; } = new(4096);
public static SigningCredentials Credentials()
{
return new SigningCredentials(new RsaSecurityKey(RSA), SecurityAlgorithms.RsaSha512)
{
CryptoProviderFactory = new CryptoProviderFactory { CacheSignatureProviders = false }
};
}
}
这是一个简单的静态类,可生成 RSA 密钥和相关的签名凭据。它有更多代码,但这对我的问题并不重要...
然后我有代码使用System.IdentityModel.Tokens.Jwt和System.Security.Claims生成JWT令牌:
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Jti, account.Id.ToString()),
new Claim(JwtRegisteredClaimNames.Sub, account.Name),
new Claim(JwtRegisteredClaimNames.Name, account.FullName),
new Claim(JwtRegisteredClaimNames.GivenName, account.FirstName),
new Claim(JwtRegisteredClaimNames.FamilyName, account.LastName),
new Claim(JwtRegisteredClaimNames.Birthdate, account.Birthdate.ToString()),
new Claim(JwtRegisteredClaimNames.Email, account.Email.ToString()),
};
var token = new JwtSecurityToken
(
issuer: host,
audience: audience,
claims: claims,
notBefore: DateTime.UtcNow,
expires: DateTime.UtcNow.AddHours(4),
Security.Credentials()
);
同样,不要太具有挑战性。我的代码中的一些数据声明,这是我自己的具有基本用户数据的类。这变成了一个签名的令牌。它产生了这个令牌:
eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJhYmQ3NjUxMS1jNmNmLTQzZjUtOGE1Zi1iZjEzZTg0NGM1ZmEiLCJzdWIiOiJ3aW0iLCJuYW1lIjoiV2ltIFRlbiBCcmluayIsImdpdmVuX25hbWUiOiJXaW0iLCJmYW1pbHlfbmFtZSI6IlRlbiBCcmluayIsImJpcnRoZGF0ZSI6IjExLTctMTk2NiIsImVtYWlsIjoid2ltQGV4YW1wbGUuY29tIiwibmJmIjoxNjQwNjU1MDA1LCJleHAiOjE2NDA2Njk0MDUsImlzcyI6ImxvY2FsaG9zdDo3MTkwIiwiYXVkIjoiL1Rva2VuL0xvZ2luIn0.iFn6DKvHxW_Vd6bxlLs4quQwCyYWpL7bbyMJSTVMxS4RRQ9GxM9IvgoymEqyn9YNBc68TFULNPRVBFE8_mF-IpYt1NIGtp8p7u9laMRegEfXyvJFislDcPZoMbD5xjB18xwUwTpkNjdX4svzFIR8mQT5bLcb5BojFLhxUVT-oJ8G_f0lD0XWJkDo40OW9aHECjIOOu_KfeYZiPdiuo-q9yed6WN1-dgqz4ykWOYC7FoMA0ZYogG5pRvmVLOq8haiEDEJRszbhjj6CLt6h_hlwOS0mMZF6a7Ag5mN4lI2UtEot-jYyXM72eXgBPm_bWNsa6RG_m9vFf4EElK4ekfFd3V_qkAnZ8XEhfTcRD8ASEVjXg8hTI5SY4LFyrggso44HFN5oEoVWlVVcGZxEG2R6LspJSFD4xkrVUUeQvt7IbBL1ViflSfGYp6-cLMPfxo3qZvItC7DxP_8aAygNmHi0_T8BxGNLnOwqrPtDOjKzw4SqEEwBf5S5R6O_dufhauAVvvS_rKQnkEdq-MNNNW5U90ytauCcAgFEGa03MN3E4hhQKUE5y70wCStrIFcBtJezf32U8V7SHv1WrVMpnQXxQoLneZh3b7QsthKCh49ypUS Ljw4yL9VVur2K0oV8NsLnwoqH5dCVFuq7YHmreiTa-ZUIFVrgWYMzMqR8hG7Ato
现在我想使用以下代码将其转换回令牌:
var tokenData = new JwtSecurityToken(tokenString);
这将再次从字符串生成令牌,但它当然没有经过验证。我需要验证此令牌的签名。
需要明确的是:这不适用于 ASP.NET Core 应用程序,但我确实将 .NET Core 用于此控制台应用程序。这是一个简单的工具,它连接到包含字符串形式的令牌的数据库,它只需要使用特定的 RSA 密钥验证其中的每个令牌。 (也存储在安全位置。)此数据库中的令牌来自一个 Web 应用程序,该应用程序使用此表进行日志记录,但显然某些令牌使用错误或无效的密钥进行签名,我需要一种快速方法来查找哪些令牌在其中无效这个日志。
那么,验证这些签名的最简单方法是什么?
还有一个更新:我的代码正在使用Microsoft.AspNetCore.Authentication.JwtBearer,由于某种原因,它在验证期间导致了一些意外行为和错误。当我将它踢出并用System.IdentityModel.Tokens.Jwt 替换它时,一切都开始工作了。
这两个包在类和其他部分非常相似,我不确定它们之间有何不同,但它们确实不同。一种是使用 OpenID,另一种是使用 JWT。切换到最后一个解决了我的问题...
【问题讨论】:
-
仅供参考,从 2011 年开始,Google 显示了太多选项,并且许多使用过时的功能或第三方软件包,它们不再那么好用了。 (或者对于 .NET 核心是否已过时...)
-
这能回答你的问题吗? c# How to verify signature JWT?
-
@Progman 不,这是一个早于 .NET Core 的旧解决方案并且不起作用。另外,感觉现在是否应该存在更简单的方法。
-
请edit 您的问题包含您遇到的问题的 MCVE。使用
JwtSecurityTokenHandler.ValidateToken()效果很好,请参阅dotnetfiddle.net/8GGlR4 -
@Progman 这个问题已经有足够的例子了。至于那个.NET Fiddle链接:我明白了:找不到方法:'Void Microsoft.IdentityModel.Tokens.InternalValidators.ValidateLifetimeAndIssuerAfterSignatureNotValidatedJwt(Microsoft.IdentityModel.Tokens.SecurityToken,System.Nullable
1<System.DateTime>,System.Nullable1,System .String,Microsoft.IdentityModel.Tokens.TokenValidationParameters,System.Text.StringBuilder)”。 那么为什么会出现这个异常?