c# - 来自 OnTokenValidated 事件侦听器的 TokenValidatedContext 的安全令牌缺少最后一个字符串段
问题描述
我将Microsoft.AspNetCore.Authentication.JwtBearer和System.IdentityModel.Tokens.Jwt用于我的 .NET Core 项目。
每当我生成一个新令牌时,我都会将其存储到数据库中。首先这是我生成新令牌的方式
public string GenerateToken(Dictionary<string, object> payload)
{
DateTime tokenExpiresAt = DateTime.Now.AddMilliseconds(1); // from config
byte[] symmetricKey = Convert.FromBase64String("secret"); // from config
SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(symmetricKey);
SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
{
Claims = payload,
Expires = tokenExpiresAt,
SigningCredentials = new SigningCredentials(symmetricSecurityKey,
SecurityAlgorithms.HmacSha256Signature)
};
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
SecurityToken securityToken = tokenHandler.CreateToken(tokenDescriptor);
string token = tokenHandler.WriteToken(securityToken);
return token;
}
生成的样本令牌是
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIxIiwibmJmIjoxNTk1NDQ1NjMxLCJleHAiOjE1OTU0NDU2OTEsImlhdCI6MTU5NTQ0NTYzMX0.cWvSpKC_yYao2I_ziW_vxjxx
如果客户端尝试访问受保护的端点,默认配置将处理基本验证(在启动文件的 DI 设置中配置)
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwtBearerOptions =>
{
byte[] symmetricKey = Convert.FromBase64String("secret"); // from config
SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(symmetricKey);
jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
ValidateIssuer = false,
ValidateAudience = false,
IssuerSigningKey = symmetricSecurityKey,
};
jwtBearerOptions.Events = new JwtBearerEvents()
{
OnTokenValidated = ProcessAfterTokenValidation
};
});
如您所见,我向OnTokenValidated
事件侦听器添加了一个方法。此方法应检查令牌是否存在于数据库中。
public async Task ProcessAfterTokenValidation(TokenValidatedContext tokenValidatedContext)
{
JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
string token = jwtSecurityTokenHandler.WriteToken(tokenValidatedContext.SecurityToken);
// ... check if token exists in db ...
}
该方法的问题在于生成的令牌不是存储在数据库中的确切令牌。缺少最后一段。token 变量保存了这个
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIxIiwibmJmIjoxNTk1NDQ1NjMxLCJleHAiOjE1OTU0NDU2OTEsImlhdCI6MTU5NTQ0NTYzMX0。
缺少的最后一部分是
cWvSpKC_yYao2_ziW_ahjjHpUl2SgUZvCmsjXntxCOI
有人知道为什么令牌的最后一部分丢失了吗?
感谢帮助!
解决方案
令牌的最后一部分是签名。OnTokenValidated方法的目的是提供 ClaimsIdentity。签名不是令牌持有者声明的组成部分。
如果您在发行方有密钥轮换策略,则给定用户可以在密钥轮换之前和之后提出具有不同签名的相同声明。
用户的身份来自发行者加上任何标识用户的声明的组合(例如username
,在您的示例中的令牌中)。
在您的情况下,由于您是发行者,因此减去签名的令牌仅表示用户已成功通过您的令牌发行端点进行身份验证的证明。令牌中的声明应该指向数据库记录,而不是令牌本身。
推荐阅读
- r - 删除具有多个分组条件的重复项
- c++ - C++中的三元运算符生成什么对象?
- server - 服务器 Nginx + Apache CentOS7
- python - Python - 剥离元组的每个元素
- typescript - 如何在 TypeScript 中定义一组通用对象,每个项目都有不同的模板参数
- ruby-on-rails - WordPress 上的搜索表单在 rails 应用程序上显示结果
- android - 无法在 Android 中为 flutter_downloader 打开下载的文件
- c# - 协商后不检查 WebSocket 连接的访问令牌
- flutter - 使用 Flutter 在谷歌地图上绘制圆弧
- java - 用于对象检测的带有 model.tflite 的 Android 应用