asp.net core token验证需严格按序注册userouting→useauthentication→useauthorization→useendpoints,jwt须配置addjwtbearer()并确保密钥、issuer/audience一致;token必须含sub声明且authorization头格式正确,iis/nginx需透传该头;开发环境应条件化注册授权策略而非用#if debug绕过。

Token验证不是加个中间件就完事
ASP.NET Core 的 UseAuthentication() 和 UseAuthorization() 必须按顺序注册,且位置必须在 UseRouting() 之后、UseEndpoints() 之前。漏掉或错序会导致 HttpContext.User 始终为空,所有 [Authorize] 都静默放行或一律 401。
- JWT 验证需显式配置
AddJwtBearer(),不能只靠AddAuthentication() - 密钥(
SecurityKey)必须与签发时完全一致,Base64 编码的字符串要先Convert.FromBase64String()再传入SymmetricSecurityKey -
ValidIssuer和ValidAudience若设为空或null,默认校验会失败;设为string.Empty才跳过对应校验
从 AuthorizationHeader 提取 Token 的坑
客户端必须用 Authorization: Bearer xxx 格式传 Token,中间件默认只认 Bearer scheme。如果前端拼成 Bearerxxx(少空格)或 bearer xxx(小写),JwtBearerHandler 会直接忽略,不报错也不验证。
- 调试时可临时在
OnAuthenticationFailed回调里加Console.WriteLine(e.Exception.Message)查原因 - 若 API 允许 query string 传 Token(如
?token=xxx),需自定义IClaimsTransformation或重写JwtBearerEvents.OnMessageReceived - 注意:IIS 或反向代理可能默认剥离
Authorization头,需在 web.config 或 Nginx 配置中显式透传
ValidateToken 触发但 User.Identity.IsAuthenticated 仍为 false
常见原因是 Token 中缺少必需的声明(claim)。JWT 默认只把 name 映射为 Identity.Name,但 IsAuthenticated 依赖 sub(subject)是否存在且非空。如果签发时没写 sub,即使签名和有效期都对,用户也会被判定为未认证。
- 签发 Token 时务必包含
sub和iat(推荐也加exp) - 用
System.IdentityModel.Tokens.Jwt库签发时,别直接 newJwtSecurityToken后漏掉claims参数 - 调试可用在线工具(如 jwt.io)粘贴 Token 查看载荷,确认
sub字段存在且值合法
开发环境绕过验证?别用 #if DEBUG
在代码里写 #if DEBUG ... [AllowAnonymous] ... #endif 看似方便,但一旦发布到测试环境却忘了删,就是严重安全漏洞。更稳妥的方式是条件注册策略:
if (env.IsDevelopment())
{
services.AddAuthorization(options =>
{
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
}
else
{
services.AddAuthorization();
}
或者统一用策略名 + 运行时开关,避免编译期硬编码。Token 验证链路一旦松动,权限控制就形同虚设——而问题往往不出在加密逻辑,出在 header 解析、claim 映射、或部署配置的细微偏差上。











