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

.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 11:54:50