ASP.NET Core Web API基于角色的授权策略无法生效问题求助
问题根因
你遇到的[Authorize(Policy = "readpolicy")]不生效的问题,主要来自三个核心错误:
- 中间件顺序错误,
UseHttpsRedirection放在了身份验证/授权中间件之后,跳转时丢失了认证上下文 - 认证配置冲突,同时混用了Jwt和Cookie两种认证逻辑,
AddDefaultIdentity默认自带Cookie认证,覆盖了你之前设置的Jwt默认方案,且你登录时用的SignInAsync是Cookie认证专属逻辑,和Jwt无状态认证的逻辑完全不匹配 - 存在大量冗余配置,干扰了授权逻辑的正常执行
修复步骤
1. 移除所有冗余配置
你是前后端分离的Web API,用Jwt做认证,以下代码完全不需要,可以直接删除:
- 自己手动构建的
IConfigurationRoot configuration,WebApplication.CreateBuilder已经默认加载了appsettings.json、环境变量、环境专属配置文件,直接用builder.Configuration即可 - 所有Cookie相关配置:
CookiePolicyOptions配置、AddCookie()注册、UseCookiePolicy()中间件 AddDefaultIdentity,你不需要Identity自带的登录页、Cookie认证等逻辑,换成更轻量的AddIdentityCore即可,避免覆盖Jwt默认配置
2. 修正中间件顺序
正确的中间件执行顺序必须是:UseHttpsRedirection → UseRouting → UseAuthentication → UseAuthorization → 端点映射
3. 修正Jwt配置与登录逻辑
- 在你的
ConfigureJwtBearerOptions类中,确保TokenValidationParameters的RoleClaimType设置为ClaimTypes.Role,保证授权时能正确识别角色声明 - 废弃当前的
HttpContext.SignInAsync登录逻辑:Jwt是无状态认证,不需要服务端保存登录状态,你需要在验证完谷歌登录的payload后,生成Jwt Token返回给React前端,前端后续所有请求在请求头携带Authorization: Bearer <生成的Jwt Token>即可
梳理后的完整Program.cs代码
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using WTSS_Portal_Middleware.Data; var builder = WebApplication.CreateBuilder(args); // 注册数据库上下文 builder.Services.AddDbContext<TSTWTSSPortalContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); builder.Services.AddDbContext<UserDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("UserDbConnection"))); // 注册核心Identity服务,仅用角色、用户管理功能,不加载默认Cookie/页面逻辑 builder.Services.AddIdentityCore<IdentityUser>() .AddRoles<IdentityRole>() .AddEntityFrameworkStores<UserDbContext>(); // 注册JWT认证 builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(); builder.Services.AddTransient<IConfigureOptions<JwtBearerOptions>, ConfigureJwtBearerOptions>(); // 注册授权策略 builder.Services.AddAuthorization(options => { options.AddPolicy("readpolicy", policy => policy.RequireRole("WTSS support", "System owner", "Regular user", "Company owner", "Unauthenticated")); options.AddPolicy("writepolicy", policy => policy.RequireRole("WTSS support", "System owner")); }); // 注册基础服务 builder.Services.AddControllers(); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new() { Title = "WTSS_Portal_Middleware", Version = "v1" }); }); var app = builder.Build(); // 配置中间件管道 if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "WTSS_Portal_Middleware V1"); c.RoutePrefix = string.Empty; }); } // 注意顺序不能乱 app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
补充说明
你之前[Authorize]生效但带Policy的不生效的原因是:[Authorize]只校验请求是否经过认证,不校验角色权限,所以只要Jwt或者Cookie任意一种认证通过就可以访问,而带Policy的校验需要正确读取到请求中的角色声明,因为之前的配置冲突,角色声明没有被授权逻辑正确识别,所以校验失败无法命中接口。
内容的提问来源于stack exchange,提问作者congying pan
相关产品推荐
相关产品推荐

