必须在Program.cs中调用AddJwtBearer()配置JWT认证,显式设置TokenValidationParameters各验证开关为true,严格匹配issuer/audience字符串,正确使用SecurityKey和SigningCredentials,并确保Authorization头格式为“Bearer ”。

怎么用 AddJwtBearer 配置认证中间件
ASP.NET Core 6+ 默认不启用 JWT 认证,必须手动注册并配置 AddJwtBearer。漏掉这步,[Authorize] 会静默失败(返回 401 但没提示),不是代码报错,而是整个认证流程压根没启动。
- 必须在
Program.cs的builder.Services.AddAuthentication()后链式调用AddJwtBearer(),不能只写AddAuthentication() -
TokenValidationParameters里ValidateIssuerSigningKey、ValidateAudience等开关默认是false,生产环境务必显式设为true,否则签名无效的 token 也能过 - 密钥必须用
SecurityKey实例(比如new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your-32-byte-secret"))),直接传字符串会编译失败 - 如果用
RS256,要加载RSA实例,别误用SymmetricSecurityKey,否则运行时报ArgumentException: IDX10623
生成 token 时 SigningCredentials 和 EncryptingCredentials 别混用
JWT 分签名(sign)和加密(encrypt)两层,.NET 的 System.IdentityModel.Tokens.Jwt 默认只做签名;加密封装要用 JWE,但绝大多数 Web API 只需要签名版 JWT(JWS),强行加密反而让前端解析不了。
- 生成 token 用
new JwtSecurityToken(..., signingCredentials: creds)就够了,encryptingCredentials参数留空或删掉 -
SigningCredentials的算法必须和AddJwtBearer配置的TokenValidationParameters.ValidateAlgorithm一致,比如都用SecurityAlgorithms.HmacSha256 - 别把密钥硬编码在代码里,改用
IConfiguration读取,例如builder.Configuration["Jwt:Key"],否则部署到不同环境要改代码 - 过期时间用
expires: DateTime.UtcNow.AddMinutes(30),别用DateTime.Now(时区问题导致 token 提前失效)
HttpContext.User.Identity.IsAuthenticated 一直是 false?检查 issuer/audience 是否严格匹配
这是最常被忽略的点:token 里的 iss(issuer)和 aud(audience)字段,必须和 AddJwtBearer 配置中 ValidIssuer、ValidAudience 完全一致(包括末尾斜杠、大小写),一个字符不对就认证失败,且不会报具体原因。
- 生成 token 时显式指定:
new JwtSecurityToken(issuer: "https://api.example.com", audience: "https://api.example.com", ...) - 配置验证参数时也写死相同值:
ValidIssuer = "https://api.example.com",别用变量拼接或漏掉协议头 - 如果后端有多个子域(如
auth.example.com和api.example.com),audience必须是接收方的域名,不是签发方的 - 调试时可临时加日志:
OnAuthenticationFailed = ctx => { Console.WriteLine(ctx.Exception.Message); },看到IDX10205错误基本就是 issuer/audience 不匹配
为什么 Postman 能过、前端 Axios 却 401?注意 Authorization 请求头格式
JWT 必须放在 Authorization: Bearer 头里,少一个空格、多一个引号、或者写成 authorization(小写)都会被中间件忽略——.NET 的 JwtBearerHandler 对头字段名大小写敏感,且只认 Bearer 前缀。
- 前端发请求必须写全:
headers: { 'Authorization': 'Bearer ' + token },注意Bearer后有一个英文空格 - Postman 默认加的是正确格式,但手写 cURL 或某些 SDK(比如老版本 axios)可能漏空格,抓包看请求头就能确认
- 如果用 Cookie 存 token,
AddJwtBearer默认不从 Cookie 读,得自己写Events.OnMessageReceived拦截并赋值ctx.Token - IIS 或 Nginx 可能默认过滤带下划线的 Header(如
Authorization),Linux 上尤其要注意,Nginx 要加underscores_in_headers on;
真正卡住人的往往不是算法或密钥,而是 issuer 字符串多了一个斜杠,或是前端拼 Authorization 头时忘了空格。这些地方没日志、不报错,只默默返回 401。











