从 TokenValidatedContext 获取签名
get signature from TokenValidatedContext
我正在为我的 .NET Core 项目使用 Microsoft.AspNetCore.Authentication.JwtBearer 和 System.IdentityModel.Tokens.Jwt 包。
配置服务时,我正在向 OnTokenValidated
事件添加逻辑。
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwtBearerOptions =>
{
// ... set TokenValidationParameters ...
jwtBearerOptions.Events = new JwtBearerEvents()
{
OnTokenValidated = (tokenValidatedContext) =>
{
JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
string tokenWithoutSignature = jwtSecurityTokenHandler.WriteToken(tokenValidatedContext.SecurityToken);
// ... full token from request? ...
}
};
});
因为我只知道上下文 return 没有签名的令牌我想知道我怎么能
- 要么获得带签名的完整令牌
- 或签名另外将其添加到
tokenWithoutSignature
字符串
如果这不可能:
我正在以这种方式生成新令牌
public string GenerateAccessToken(IDictionary<string, object> payload)
{
SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(Convert.FromBase64String("secret from config"));
SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
{
Claims = payload,
Expires = DateTime.Now, // value from config
SigningCredentials = new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256Signature)
};
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
SecurityToken securityToken = tokenHandler.CreateToken(tokenDescriptor);
string token = tokenHandler.WriteToken(securityToken);
return token;
}
也许我可以找回
- 没有签名的token字符串
- 只有签名
在这个方法中?
如果没有效果:
因为我知道不记名令牌总是包含三个部分,例如
header.payload.signature
我可以将字符串段拆分为一个数组,从数组中取出第一个和第二个元素并创建一个新字符串
firstString + . + secondString
那应该给我没有签名的令牌。是否有更好的想法从完整令牌中截断签名?
我为什么要实现这个?
本题基于此题
我正在使用访问和刷新令牌。在验证期间,我必须将请求中的令牌与数据库中的令牌进行比较。数据库中的令牌也包含签名。所以我面临着与上面链接相同的问题。
这就是为什么我想到了多种解决方案并将它们写在这里的原因。如果 TokenValidatedContext
无法 return 我的签名似乎我必须将 JWT 存储到没有签名的数据库中。同样对于这种情况,我需要将签名与生成的 JWT 分开。
没有 使用刷新令牌,我只将用户的最长会话生命周期存储到数据库中。流程是基于这个想法
Only store the time of the JWT with the highest lifetime to the database instead of the whole JWT
使用刷新令牌我想出了以下流程。 既然您知道 OnTokenValidated
处理验证逻辑,那么下面的逻辑是额外的。我有一个数据库 table
username | access_token | refresh_token | refresh_token_expires_at
主键是用户名+access_token的复合键。刷新令牌只是一些像这样生成的随机字符串
public string GenerateRefreshToken()
{
var randomNumber = new byte[32];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(randomNumber);
return Convert.ToBase64String(randomNumber);
}
}
这就是我为其存储额外到期日期的原因。它应该可以在一段时间后过期。
正在登录
将用户生成的访问和刷新令牌及其过期时间存储到数据库中。将完整访问令牌或无签名访问令牌存储到数据库(取决于此问题的解决方案)。
命中受保护的端点
检查数据库中是否存在该用户的访问令牌。
正在刷新端点
检查数据库刷新令牌是否已过期。如果不是,请将此与请求中的刷新令牌进行比较。如果一切正常,从数据库中删除旧的访问和刷新令牌,并将新生成的访问和刷新令牌存储到数据库中。
退出
从数据库中删除该访问及其连接的刷新令牌。
为什么要操纵令牌?如果只是为了验证令牌,您可以使用下面的代码。
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
//ValidIssuer = Configuration["Issuer"],
//ValidAudience = Configuration["Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Key"]))
};
});
和
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
app.UseMvc();
}
我不太明白你为什么要这样做,但如果你只需要原始令牌,你可以使用以下之一:
o.Events = new JwtBearerEvents
{
OnTokenValidated = (context) =>
{
var securityToken = (System.IdentityModel.Tokens.Jwt.JwtSecurityToken)context.SecurityToken;
var token = securityToken.RawData; // "ey...."
var tokenHeader = securityToken.RawHeader; // "ey...."
var tokenPayload = securityToken.RawPayload; // "ey...."
var tokenSignatur = securityToken.RawSignature; // "ey...."
var fullBearerHeader = context.Request.Headers["Authorization"]; // "Bearer ey..."
return Task.CompletedTask;
}
};
你可能想让代码在类型转换等方面更安全一些,但它应该给你令牌。
我正在为我的 .NET Core 项目使用 Microsoft.AspNetCore.Authentication.JwtBearer 和 System.IdentityModel.Tokens.Jwt 包。
配置服务时,我正在向 OnTokenValidated
事件添加逻辑。
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwtBearerOptions =>
{
// ... set TokenValidationParameters ...
jwtBearerOptions.Events = new JwtBearerEvents()
{
OnTokenValidated = (tokenValidatedContext) =>
{
JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
string tokenWithoutSignature = jwtSecurityTokenHandler.WriteToken(tokenValidatedContext.SecurityToken);
// ... full token from request? ...
}
};
});
因为我只知道上下文 return 没有签名的令牌我想知道我怎么能
- 要么获得带签名的完整令牌
- 或签名另外将其添加到
tokenWithoutSignature
字符串
如果这不可能:
我正在以这种方式生成新令牌
public string GenerateAccessToken(IDictionary<string, object> payload)
{
SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(Convert.FromBase64String("secret from config"));
SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
{
Claims = payload,
Expires = DateTime.Now, // value from config
SigningCredentials = new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256Signature)
};
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
SecurityToken securityToken = tokenHandler.CreateToken(tokenDescriptor);
string token = tokenHandler.WriteToken(securityToken);
return token;
}
也许我可以找回
- 没有签名的token字符串
- 只有签名
在这个方法中?
如果没有效果:
因为我知道不记名令牌总是包含三个部分,例如
header.payload.signature
我可以将字符串段拆分为一个数组,从数组中取出第一个和第二个元素并创建一个新字符串
firstString + . + secondString
那应该给我没有签名的令牌。是否有更好的想法从完整令牌中截断签名?
我为什么要实现这个?
本题基于此题
我正在使用访问和刷新令牌。在验证期间,我必须将请求中的令牌与数据库中的令牌进行比较。数据库中的令牌也包含签名。所以我面临着与上面链接相同的问题。
这就是为什么我想到了多种解决方案并将它们写在这里的原因。如果 TokenValidatedContext
无法 return 我的签名似乎我必须将 JWT 存储到没有签名的数据库中。同样对于这种情况,我需要将签名与生成的 JWT 分开。
没有 使用刷新令牌,我只将用户的最长会话生命周期存储到数据库中。流程是基于这个想法
Only store the time of the JWT with the highest lifetime to the database instead of the whole JWT
使用刷新令牌我想出了以下流程。 既然您知道 OnTokenValidated
处理验证逻辑,那么下面的逻辑是额外的。我有一个数据库 table
username | access_token | refresh_token | refresh_token_expires_at
主键是用户名+access_token的复合键。刷新令牌只是一些像这样生成的随机字符串
public string GenerateRefreshToken()
{
var randomNumber = new byte[32];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(randomNumber);
return Convert.ToBase64String(randomNumber);
}
}
这就是我为其存储额外到期日期的原因。它应该可以在一段时间后过期。
正在登录
将用户生成的访问和刷新令牌及其过期时间存储到数据库中。将完整访问令牌或无签名访问令牌存储到数据库(取决于此问题的解决方案)。
命中受保护的端点
检查数据库中是否存在该用户的访问令牌。
正在刷新端点
检查数据库刷新令牌是否已过期。如果不是,请将此与请求中的刷新令牌进行比较。如果一切正常,从数据库中删除旧的访问和刷新令牌,并将新生成的访问和刷新令牌存储到数据库中。
退出
从数据库中删除该访问及其连接的刷新令牌。
为什么要操纵令牌?如果只是为了验证令牌,您可以使用下面的代码。
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
//ValidIssuer = Configuration["Issuer"],
//ValidAudience = Configuration["Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Key"]))
};
});
和
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
app.UseMvc();
}
我不太明白你为什么要这样做,但如果你只需要原始令牌,你可以使用以下之一:
o.Events = new JwtBearerEvents
{
OnTokenValidated = (context) =>
{
var securityToken = (System.IdentityModel.Tokens.Jwt.JwtSecurityToken)context.SecurityToken;
var token = securityToken.RawData; // "ey...."
var tokenHeader = securityToken.RawHeader; // "ey...."
var tokenPayload = securityToken.RawPayload; // "ey...."
var tokenSignatur = securityToken.RawSignature; // "ey...."
var fullBearerHeader = context.Request.Headers["Authorization"]; // "Bearer ey..."
return Task.CompletedTask;
}
};
你可能想让代码在类型转换等方面更安全一些,但它应该给你令牌。