.NET 2.2迁移至3.1后Controller接口调用被重定向至登录页问题
.NET 2.2迁移至.NET 3.1后API接口授权失效重定向登录页问题
近期将基于Razor Pages构建、包含少量对外数据接口Controller的.NET 2.2网站迁移至.NET 3.1(后续计划升级至.NET 6/8)。迁移后前端Razor Pages功能正常,但所有带[Authorize(Policy = "ApiKeyPolicy")]授权的Controller接口均无法正常工作——按常规方式传递ApiKey后,接口调用会被重定向至/Account/Login页面,而非返回授权错误。
相关代码片段
Startup.cs 认证授权配置
services .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { options.LoginPath = "/Account/Login"; options.LogoutPath = "/Account/Logout"; }); services.AddTransient<IAuthorizationHandler, ApiKeyRequirementHandler>(); services.AddAuthorization(authConfig => { authConfig.AddPolicy("ApiKeyPolicy", policyBuilder => policyBuilder .AddRequirements(new APIKeyRequirement())); }); services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; });
Startup.cs 服务配置(注释为.NET 2.2原配置)
//services // .AddMvc() // .SetCompatibilityVersion(CompatibilityVersion.Version_2_1) // .AddJsonOptions(options => { // options.SerializerSettings.ContractResolver = new DefaultContractResolver(); // options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; // }); services.AddRazorPages(); services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.ContractResolver = new DefaultContractResolver(); options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; });
中间件配置
app.UseRouting(); app.UseSession(); app.UseCookiePolicy(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); endpoints.MapControllerRoute( name: "default", "{controller=Home}/{action=Index}/{id?}"); endpoints.MapControllers(); }); //app.UseMvc(routes => //{ // routes.MapRoute( // name: "default", // template: "{controller=Home}/{action=Index}/{id?}"); //});
Controller代码(简化版)
[Authorize(Policy = "ApiKeyPolicy")] public class StorefrontController : Controller { // 示例方法 [HttpGet] public virtual async Task<IActionResult> PendingOrders() { // 业务逻辑 } }
ApiKey检查逻辑
private void RequirementCheck(AuthorizationHandlerContext context, APIKeyRequirement requirement) { if (context.Resource is AuthorizationFilterContext authorizationFilterContext) { var apiKey = authorizationFilterContext.HttpContext.Request.Headers[API_KEY_HEADER_NAME].FirstOrDefault(); if (apiKey != null && requirement.APIKey == apiKey) { context.Succeed(requirement); } else { var authFilterContext = context.Resource as AuthorizationFilterContext; authFilterContext.Result = new UnauthorizedResult(); context.Succeed(requirement); } } }
排查过程
- 调整Startup.cs中服务注册顺序,问题未解决。
- 给Controller添加
[AllowAnonymous]特性后,接口可正常访问,说明请求能正确路由到目标Controller,但ApiKey授权逻辑未生效。 - 调试发现ApiKey检查逻辑中
context.Resource并非AuthorizationFilterContext类型,推测这是.NET 3.1的框架变更导致授权逻辑无法执行,进而触发Cookie认证的登录重定向。
目前团队正在.NET 8中重写相关功能,但仍希望解决该.NET 3.1版本的问题。
内容的提问来源于stack exchange,提问作者Jason S
相关产品推荐
相关产品推荐

