authentication 中间件必须在 authorization 之前注册,即 useauthentication() 必须位于 useauthorization() 之前,否则 user.identity.isauthenticated 恒为 false;同时需显式指定默认认证方案并正确配置 tokenvalidationparameters 和 cookie 过期策略。

Authentication 中间件必须在 Authorization 之前注册
ASP.NET Core 的请求管道对中间件顺序极其敏感。app.UseAuthentication() 必须出现在 app.UseAuthorization() 之前,否则 User.Identity.IsAuthenticated 始终为 false,即使 token 有效或 Cookie 已携带凭证。
常见错误现象:登录成功跳转后 User 为空、API 返回 401 却没触发认证逻辑、[Authorize] 特性完全不生效。
- 正确顺序示例:
UseRouting()→UseAuthentication()→UseAuthorization()→UseEndpoints() - 若使用 Minimal Hosting 模型(.NET 6+),对应为:
builder.Services.AddAuthentication(...)+app.UseAuthentication()在app.UseAuthorization()前调用 - 不要在
UseEndpoints内部或之后插入UseAuthentication
AddAuthentication 需显式指定默认 Scheme
不指定默认方案时,[Authorize] 会因找不到匹配的 handler 而直接拒绝请求,报错信息类似:InvalidOperationException: No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found.
典型场景:JWT Bearer 和 Cookie 认证共存时,必须明确告诉框架哪个是默认用于 [Authorize] 的方案。
- 只用 JWT:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(...) - 只用 Cookie:
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(...) - 多 scheme 共存但需默认行为:
AddAuthentication("MyDefaultScheme"),再通过AddScheme<toptions thandler></toptions>注册具体实现 - 注意:Scheme 名字必须和
AddXxx方法传入的字符串严格一致(大小写敏感)
JWT Bearer 配置易漏掉 TokenValidationParameters
仅调用 AddJwtBearer() 不足以让 token 校验真正生效。缺省配置下,ValidateIssuerSigningKey、ValidateAudience 等均为 false,意味着任何签发者、任意 audience 的 token 都会被接受——这在生产环境等同于未认证。
真实部署中,至少应启用签名密钥验证与 issuer/audience 校验,并确保 IssuerSigningKey 是 SymmetricSecurityKey 或 RsaSecurityKey 实例,而非原始字符串。
- 关键参数必须设置:
options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, ValidateIssuer = true, ValidateAudience = true, ... } -
ValidIssuer和ValidAudience必须与签发 token 时使用的值完全一致 - 若用
symmetricKey,记得用Encoding.UTF8.GetBytes("...")构造SymmetricSecurityKey,别直接传字符串 - 开发阶段可临时设
ValidateLifetime = false方便调试,但上线前务必恢复为true
Cookie 认证的 SlidingExpiration 和 ExpireTimeSpan 容易混淆
ExpireTimeSpan 控制 cookie 的绝对过期时间(如 120 分钟),而 SlidingExpiration = true 表示只要用户持续活动,就不断刷新 cookie 过期时间——但这仅在每次请求触发认证 handler 时才生效,不是自动后台刷新。
典型问题:用户保持页面打开但无操作,2 小时后刷新页面仍 401;或误以为开启 sliding 后 session 就“永不过期”,结果发现登出逻辑失效。
-
ExpireTimeSpan是硬上限,sliding 不会突破它 - 必须配合
Cookie.HttpOnly = true(默认)和Cookie.Secure = true(HTTPS 环境下)防止 XSS/中间人窃取 - 若用
SignInAsync且未传AuthenticationProperties,则采用全局配置;若手动传参,其ExpiresUtc会覆盖全局ExpireTimeSpan - 注销必须调用
SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme),仅清除前端 cookie 不够
TokenValidationParameters 空着没填,以及 Cookie 的 ExpireTimeSpan 设了却忘了开 SlidingExpiration —— 这些都不是语法错误,运行时不报红,但认证就是不走预期路径。










