Policy 不生效是因为 UseAuthentication 必须在 UseAuthorization 之前注册,否则 User.Identity.IsAuthenticated 为 false 导致所有 [Authorize] 接口返回 401;同时 Token 中必须包含 Policy 所需的全部 Claim。

JWT 认证本身不提供细粒度权限控制,AddAuthorization 必须配合 Policy 才能实现角色、作用域或自定义规则的访问限制;漏配 UseAuthentication 或顺序颠倒,Policy 会静默失效。
为什么 Policy 不生效?检查中间件注册顺序
Policy 判断依赖认证结果,而 UseAuthentication 必须在 UseAuthorization 之前调用,否则 User.Identity.IsAuthenticated 始终为 false,所有带 [Authorize] 的接口都直接返回 401。
-
UseRouting()→UseAuthentication()→UseAuthorization()→UseEndpoints()是唯一可靠顺序 - 如果用了
MapControllers()但没显式调用UseAuthorization(),Policy 会被完全忽略 - 在 Minimal Hosting 模型中,
app.UseAuthentication()不能写在app.MapControllers()之后
如何定义 Role 和 Claim Policy
Role 策略适合简单场景(如 “Admin”、“User”),Claim 策略更灵活(如要求同时具备 department 和 level 两个声明)。
- Role 策略注册:
builder.Services.AddAuthorization(options => options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"))) - Claim 策略注册:
options.AddPolicy("HRManager", p => p.RequireClaim("department", "HR").RequireClaim("level", "manager")) - 控制器上使用:
[Authorize(Policy = "AdminOnly")]或[Authorize(Roles = "Admin")](后者绕过 Policy,不推荐混用)
自定义 Policy 需要实现 IAuthorizationRequirement 和 AuthorizationHandler
当权限逻辑涉及数据库查询、时间窗口、IP 白名单等动态条件时,必须写自定义 Handler。它会在每次请求时执行,注意避免同步阻塞或 N+1 查询。
- 定义要求:
public class TimeWindowRequirement : IAuthorizationRequirement { public TimeSpan Start { get; } = TimeSpan.FromHours(9); public TimeSpan End { get; } = TimeSpan.FromHours(18); } - 实现校验:
public class TimeWindowHandler : AuthorizationHandler,重写HandleRequirementAsync,用context.Succeed(requirement)或context.Fail() - 注册 Handler:
builder.Services.AddSingleton()
常见坑:Token 里没写 Claim,Policy 就查不到
Policy 校验的是 ClaimsPrincipal 中的 Claims,不是数据库字段。如果登录时只写了 new Claim(ClaimTypes.Role, "Admin"),但 Policy 要求 department,那永远不通过。
- 生成 Token 时必须显式添加所有 Policy 依赖的 Claim:
new Claim("department", "Finance") - 不要依赖
Identity.Name或User.Identity.GetUserId()来做策略判断,它们不在 Claims 集合里,除非你手动加进去 - 调试技巧:在 Controller 里打印
User.Claims.Select(c => $"{c.Type}:{c.Value}"),确认关键 Claim 确实存在
Policy 的执行是链式短路的,一个失败就终止;最易被忽略的是 Token 解析成功但 Claims 缺失,此时错误不报在认证层,而是静默拒绝,得从 User.Claims 入手排查。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











