.NET 8中如何缩小Bearer Token以解决代理拦截问题?
问题描述
我正在开发一个.NET 8 Web API应用,使用新的BearerTokenDefaults.AuthenticationScheme认证选项通过令牌对用户进行认证,配置代码如下:
services.AddAuthentication(BearerTokenDefaults.AuthenticationScheme) .AddBearerToken(options => { options.BearerTokenExpiration = TimeSpan.FromHours(24); });
登录生成令牌的代码:
var userClaimsPrincipal = ... // 生成claims principal var token = Results.SignIn(userClaimsPrincipal);
认证逻辑本身正常,但部署环境的公司代理会拦截请求头超过特定长度的HTTP请求。部分用户因拥有大量AD组对应的claims,导致令牌过大,请求被拦截。我无法修改代理配置,目前临时方案是只保留应用所需的少量claims,但想知道是否有更规范的解决方案,比如将claims存储在服务器端,令牌仅包含用于获取用户claims的ID,或者是否有无需自定义ClaimsProvider的内置机制?
解决方案
针对你的场景,.NET 8的Bearer Token认证提供了内置的引用令牌(Reference Tokens)机制,可以完美解决令牌过大的问题,无需自定义ClaimsProvider,具体实现如下:
1. 启用引用令牌模式
修改认证配置,将Bearer Token设置为引用令牌模式,此时生成的令牌不再是包含所有claims的自包含JWT,而是一个短的引用ID,实际的用户claims会存储在服务器端的令牌存储中:
services.AddAuthentication(BearerTokenDefaults.AuthenticationScheme) .AddBearerToken(options => { options.BearerTokenExpiration = TimeSpan.FromHours(24); // 启用引用令牌模式 options.UseReferenceTokens = true; // 生产环境推荐使用分布式存储(如Redis)替代默认内存存储 options.TokenStore = new DistributedTokenStore( services.BuildServiceProvider().GetRequiredService<IDistributedCache>(), services.BuildServiceProvider().GetRequiredService<ILogger<DistributedTokenStore>>() ); });
注意:默认的内存存储仅适用于单实例部署,多实例环境必须使用分布式缓存(如Redis)作为令牌存储,确保所有节点能共享用户claims数据。
2. 生成引用令牌
登录代码无需修改,Results.SignIn(userClaimsPrincipal)会自动生成引用令牌,而非自包含JWT:
var userClaimsPrincipal = ... // 生成claims principal var token = Results.SignIn(userClaimsPrincipal);
3. 补充方案
- 精简Claims:如果不想启用引用令牌,你的临时方案(仅保留应用必需的claims)仍然合理。可以在生成
ClaimsPrincipal时过滤掉不必要的AD组claims,只保留与应用权限相关的内容。 - JWT压缩:可手动实现JWT的Gzip压缩后Base64编码,但需要客户端配合解压请求头,不如引用令牌方案规范通用。
引用令牌的优势
- 令牌体积极小,彻底规避请求头过长的问题;
- 基于.NET 8内置实现,无需自定义令牌解析或Claims获取逻辑;
- 支持主动撤销令牌(自包含JWT无法主动撤销,只能等待过期),安全性更高;
- 分布式存储适配多实例部署场景,扩展性强。
内容的提问来源于stack exchange,提问作者Master_T
相关产品推荐
相关产品推荐

