You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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");
    });
});

验证步骤

  1. 应用修改后重启项目
  2. 不传递令牌请求/Program接口,应返回401 Unauthorized
  3. 传递有效令牌请求接口,应正常返回数据

内容的提问来源于stack exchange,提问作者dave_bell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 22:44:58