authentication解决“你是谁”,authorization解决“你能做什么”;asp.net core中useauthentication()必须在useauthorization()之前,否则isauthenticated恒为false;认证解析cookie或jwt生成claimsprincipal,授权基于策略检查claims并返回403。

认证和授权在 C# 里不是一回事,强行混用会出权限绕过或 403 泛滥——必须先分清 Authentication 和 Authorization 的边界。
Authentication 是谁?不是“能不能”,而是“是不是”
它只干一件事:确认当前请求背后那个“人”到底是谁。不涉及资源、不判断操作、不查角色。常见手段是验证 JWT 签名、解密 Cookie、调用 IdentityServer 或校验 Windows 身份。
- ASP.NET Core 中靠
AddAuthentication()注册方案,比如JwtBearerDefaults.AuthenticationScheme - 成功后生成
ClaimsPrincipal,里面带ClaimsIdentity,但此时它还没有任何“能访问什么”的信息 - 错误现象:token 过期、签名无效、
HttpContext.User.Identity.IsAuthenticated始终为false—— 这是认证层的问题,别急着去改授权策略
Authorization 才决定“你能动哪扇门”
它只在认证通过后才启动,检查 ClaimsPrincipal 里有没有匹配的 Claim、是否满足某条 Policy、有没有对应 Role。
- 策略定义在
AddAuthorization()里,例如options.AddPolicy("AdminOnly", p => p.RequireClaim("Role", "Administrator")) - 控制器或方法上加
[Authorize(Policy = "AdminOnly")],不是[Authorize(Roles = "Administrator")]—— 后者是旧式硬编码,无法复用、难测试、不支持声明组合 - 容易踩的坑:把角色名写成
"admin"(小写),而 token 里发的是"Administrator";或用了RequireRole()却没在 token 中塞"role"claim(注意 key 是小写role,不是Role)
Claims 是跨平台权限传递的唯一可靠载体
Windows、Linux、macOS 上没有统一的“用户组”或“SID”语义,但 Claim 是纯数据结构,可自由定义 key/value,适配任意权限模型。
- 生成 token 时务必显式添加关键声明,比如
new Claim("role", "Editor")或new Claim("scope", "orders:write") - 避免用
User.IsInRole("Admin")—— 它依赖IPrincipal的角色解析逻辑,在非 Windows 平台行为不可控;改用User.HasClaim("role", "Admin") - 自定义
IAuthorizationHandler时,直接从context.User取Claims,别试图反查数据库或调远程服务——性能和一致性都会崩
跨平台部署时最常被忽略的一点
Linux/macOS 下 WindowsIdentity.GetCurrent() 会抛异常或返回空,而很多老代码把它当默认身份源。如果你在后台服务或 CLI 工具里做本地权限校验,必须用 Environment.OSVersion.Platform 分支,并 fallback 到基于 ClaimsPrincipal 的声明驱动逻辑——否则一上 Docker 就挂。











