Fast.JwtBearer
版本 3.5.41;目标 net8.0、net9.0、net10.0;依赖 Fast.Runtime 和对应目标的 ASP.NET Core JwtBearer 包。命名空间 Fast.JwtBearer。
dotnet add package Fast.JwtBearer选择注册入口
| 入口 | 注册内容 |
|---|---|
AddJwtBearerSetting(configuration, section = "JWTSettings") | 仅设置工具使用的选项,注册分布式内存缓存回退;另有选项回调重载 |
AddJwtBearerAuthentication(configuration, section = "JWTSettings") | 设置 Bearer 认证,适合自己管理授权流程;另有选项回调重载 |
AddJwtBearer(configuration, section = "JWTSettings") | 完整认证、策略处理器、发现的 IJwtBearerHandle,启用时增加 MVC 全局授权过滤器;另有选项回调重载 |
注册方法返回 IServiceCollection。完整宿主仍需要认证/授权中间件以及端点映射。
以下为消费端 Program.cs,使用 Microsoft.NET.Sdk.Web,目标选择本页列出的 .NET 8、9 或 10,并安装上方指定包。app.Run() 表示正常宿主启动;本次文档维护不会执行它。
using Fast.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddJwtBearer(builder.Configuration);
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();示例要求宿主通过外部配置提供签名密钥,不内置可运行的公共密钥值。
JWTSettingsOptions 默认值
| 字段 | 默认值 / 单位 |
|---|---|
ValidateIssuerSigningKey、ValidateIssuer、ValidateAudience、ValidateLifetime | true |
IssuerSigningKey | 必须显式配置,至少 32 个 UTF-8 字节;缺失或过短抛 InvalidOperationException |
ValidIssuer / ValidAudience | Fast.NET.API / Fast.NET.Client |
ValidateAccessToken | false;失效标记检查需结合 SetExpiredToken |
ClockSkew | 5 秒 |
TokenExpiredTime | 20 分钟 |
RefreshTokenExpireTime | 1440 分钟 |
RequireRefreshTokenCache | true |
Algorithm | JwtBearerAlgorithmEnum.HS256 |
Enable | true;不等同于跳过密钥后配置校验 |
标准注册使用 AddDistributedMemoryCache() 作为未配置共享缓存时的回退;多实例刷新重放控制必须由共享 IDistributedCache 支持。Fast.Cache.ICache 与 IDistributedCache 是不同合同,不能只安装 Redis 封装就假定自动接通。
JwtBearerUtil
| API | 返回与语义 |
|---|---|
GenerateToken(IDictionary<string, object> payload, long? expiredTime = null) | 返回访问令牌文本;expiredTime 单位分钟;会补充载荷字段,调用者不要假定字典保持原样 |
GenerateRefreshToken(string accessToken) | 返回与访问令牌关联的刷新令牌;空白或 JWT 段数不正确抛参数异常 |
GetJwtBearerToken(HttpContext, string headerKey = "Authorization", string tokenPrefix = "Bearer ") | 从请求头获取令牌;校验上下文、头名称和前缀 |
Validate/ValidateAsync | 返回包含 IsValid、JsonWebToken、TokenValidationResult 的元组;需检查 IsValid |
ReadJwtToken/SecurityReadJwtToken | 解析令牌文本,不等于完成签名、有效期和授权验证 |
Exchange/ExchangeAsync | 基于访问令牌与刷新令牌交换新令牌;参与缓存重放控制 |
AutoRefreshToken/AutoRefreshTokenAsync | 在授权流程中处理验证与自动刷新,返回是否通过 |
SetExpiredToken/SetExpiredTokenAsync | 将令牌标记失效;与对应校验设置共同生效 |
CreateTokenValidationParameters | 从设置构造认证库使用的验证参数 |
IJwtBearerHandle 包含 AuthorizeHandle、AuthorizeFailHandle、PermissionHandle、PermissionFailHandle。成功检查返回 bool;失败始终记录 Fail。仅 MVC 过滤器上下文使用非 null 自定义结果生成 HTTP 401/403;其他资源由相应授权管线响应。实现按 Scoped 注册。PermissionAttribute 与 AllowForbiddenAttribute 是该授权流程的元信息,不是独立认证器。
SignalR 的 access_token 查询参数只在已识别的 Hub 端点作为补充提取方式,并先保留已有提取逻辑;普通 HTTP 端点不因此接受查询令牌,也不因此取消授权要求。
已认证主体的令牌签发与校验
仅在应用已经验证用户身份之后调用签发方法;不能直接把未验证的请求字段当作可信身份。此类可与上面的 Program.cs 放在同一个 Web 项目,签名设置仍由宿主配置提供。
using Fast.JwtBearer;
public sealed record TokenPair(string AccessToken, string RefreshToken);
public sealed class TokenService
{
public TokenPair IssueForAuthenticatedUser(string subject)
{
ArgumentException.ThrowIfNullOrWhiteSpace(subject);
var payload = new Dictionary<string, object> { ["sub"] = subject };
string access = JwtBearerUtil.GenerateToken(payload, expiredTime: 20);
string refresh = JwtBearerUtil.GenerateRefreshToken(access);
return new TokenPair(access, refresh);
}
public async Task<bool> IsValidAsync(string token)
{
var result = await JwtBearerUtil.ValidateAsync(token);
return result.IsValid;
}
}有效期参数单位是分钟。不要记录返回的令牌,也不要把它放进 URL。ValidateAsync 的元组需要检查 IsValid;单纯 ReadJwtToken 只能读取内容,不能用于信任判断。刷新使用 ExchangeAsync(httpContext, expiredToken, refreshToken, ...),同时涉及失效策略和缓存防重放;多实例部署需要共享、具备原子消费能力的防重放存储器。退出时可调用 SetExpiredTokenAsync(httpContext, token),但仅当相应失效检查已启用时才能在后续校验中生效。
来源与验证
依据 注册实现、选项、工具 API。本轮仅源码核对,未创建真实令牌、访问缓存或启动认证宿主;新增片段未编译。
组合授权与刷新令牌安全
Fast 只对自身的 AppAuthorizeRequirement 调用 Succeed。角色、声明、第三方命名策略和显式 Fail() 不会被 AllowForbidden 或缺少自定义处理器的分支放行。非空 Fast 权限要求没有 IJwtBearerHandle 时明确拒绝;已有非 Fast 策略提供器和其他处理器在注册时保留。
AuthorizeFailHandle / PermissionFailHandle 返回自定义对象也不会清除失败状态。只有 MVC 过滤器上下文写入该对象;普通端点和 SignalR 由各自的授权管线处理失败。
AutoRefreshTokenAsync 的 true 表示当前流程可以继续,不等于每次都签发了新令牌。自动刷新在同一个标准 ClaimsPrincipal 中更新已验证身份,并沿用 Bearer 的声明映射;无法安全原地更新的自定义 Principal 在消费刷新令牌前返回 false。刷新失败不应被当作业务成功。
多实例的一次性消费由 Fast.Runtime.IRefreshTokenReplayStore 表达。Fast.Cache 注册 Redis 的原子 NX+过期实现;只有进程内 MemoryDistributedCache 可以使用内存回退。其他 IDistributedCache 必须注册原子实现,不能依靠 Get 后 Set 声称防重放。自定义实现应在默认模块注册之后注册。
默认复用宽限为 0。同一刷新令牌只有一次消费权;显式设置正的 clockSkew 参数会允许首次消费后的兼容复用窗口,应理解它不是严格的一次性消费。缓存键使用令牌摘要,不保存明文令牌。验证失败、过期或缓存消费失败都不会签发访问令牌。
RequireRefreshTokenCache 默认为 true,缺少防重放实现时拒绝刷新。为兼容已有显式配置,设为 false 且没有注册实现时可以跳过消费校验,此时没有重放保护;已注册实现仍会执行校验。
