.NET Core移除AllowAnonymous后返回404而非401问题
问题描述
我是.NET Core新手,开发过程中授权功能原本正常,但不知出现了什么变化,当移除AllowAnonymous特性后,即使传递令牌,接口也返回404而非预期的401。
项目配置代码
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); //Identity builder.Services.AddIdentity<SolUser,IdentityRole> (opt => { opt.Password.RequireNonAlphanumeric = false; opt.User.RequireUniqueEmail =true; }).AddEntityFrameworkStores<StudentDBContext>().AddDefaultTokenProviders(); var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("xx")); builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(opt => { opt.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = key, ValidateIssuer = false, ValidateAudience = false }; }); builder.Services.AddScoped<TokenService>(); // End of Identity builder.Services.AddDbContext<StudentDBContext>(); builder.Services.AddCors(opt => { opt.AddPolicy("CorsPolicy", policy =>{ policy.AllowAnyMethod().AllowAnyHeader().WithOrigins("http://localhost:3000"); policy.AllowAnyMethod().AllowAnyHeader().WithOrigins("X"); policy.AllowAnyMethod().AllowAnyHeader().WithOrigins("X"); }); }); builder.Services.AddMediatR(typeof(List.Handler)); builder.Services.AddControllersWithViews().AddNewtonsoftJson(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore); // With below we dont have to authorize at get/post level. AllowAnonymous will allow for login and register builder.Services.AddControllers(opt => { var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build(); opt.Filters.Add(new AuthorizeFilter(policy)); }); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddAutoMapper(typeof(MappingProfiles).Assembly); builder.Services.AddScoped<IEmailService,EmailService>(); builder.Services.AddFluentValidationAutoValidation(); builder.Services.AddValidatorsFromAssemblyContaining<SolStudent>(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseMiddleware<ExceptionMiddleware>(); //Top of the Middleware stack app.UseCors("CorsPolicy"); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); //Identity order important app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.MapControllerRoute( name: "default", pattern: "{controller}/{action=Index}/{id?}"); app.MapFallbackToFile("index.html"); app.Run();
控制器代码
添加AllowAnonymous时可正常工作,但移除后即使传递令牌也会返回404:
namespace netreact.Controllers { [ApiController] [Route("[controller]")] public class ProgramController : Controller { private readonly IMediator _mediator; public IActionResult Index() { return View(); } public ProgramController(IMediator mediator) { //_context = context; _mediator = mediator; } public JsonSerializerOptions options = new() { ReferenceHandler = ReferenceHandler.Preserve, WriteIndented = true }; [HttpGet] public async Task<ActionResult<List<TrialProgram>>> GetList() { return await _mediator.Send(new TrialProg.Query()); } } }
问题分析与解决
核心问题1:重复注册Controllers服务
代码中先后调用AddControllersWithViews()和AddControllers(),导致服务注册冲突。AddControllers()添加的全局授权策略会覆盖之前配置,且重复注册会干扰路由匹配逻辑——全局授权生效时,未认证请求被错误路由,返回404而非401。
解决办法:合并Controllers服务注册,将全局授权策略统一配置:
// 替换原两次Controllers注册调用 builder.Services.AddControllersWithViews(options => { var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build(); options.Filters.Add(new AuthorizeFilter(policy)); }) .AddNewtonsoftJson(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
核心问题2:控制器基类选择错误
ProgramController继承自MVC的Controller基类,却标注了Web API专用的[ApiController]特性,混合使用导致路由与认证逻辑混乱。
解决办法:改为继承Web API专用的ControllerBase,并移除无需的视图方法:
namespace netreact.Controllers { [ApiController] [Route("[controller]")] public class ProgramController : ControllerBase { private readonly IMediator _mediator; public ProgramController(IMediator mediator) { _mediator = mediator; } public JsonSerializerOptions options = new() { ReferenceHandler = ReferenceHandler.Preserve, WriteIndented = true }; [HttpGet] public async Task<ActionResult<List<TrialProgram>>> GetList() { return await _mediator.Send(new TrialProg.Query()); } } }
额外优化:CORS策略冗余简化
原CORS策略中重复调用AllowAnyMethod().AllowAnyHeader(),可简化为:
builder.Services.AddCors(opt => { opt.AddPolicy("CorsPolicy", policy => { policy.AllowAnyMethod() .AllowAnyHeader() .WithOrigins("http://localhost:3000", "X", "X"); }); });
验证步骤
- 应用修改后重启项目
- 不传递令牌请求
/Program接口,应返回401 Unauthorized - 传递有效令牌请求接口,应正常返回数据
内容的提问来源于stack exchange,提问作者dave_bell
相关产品推荐
相关产品推荐

