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

ASP.NET 6 MVC中带[Authorize]的POST操作触发405错误的解决方法

ASP.NET 6 MVC微软认证POST请求405错误问题解决

问题描述

在ASP.NET 6 MVC应用中,已实现微软身份认证登录功能:

  • 登录状态下认证Cookie过期/删除时,执行HttpGet操作会自动引导完成认证并跳转回目标页面,符合预期。
  • 未登录状态下停留在页面执行HttpPost操作时,页面跳转到微软认证页面,完成账户选择后,浏览器出现HTTP ERROR 405错误。

期望行为:带[Authorize]属性的HttpPost操作,在未登录时能像GET请求一样,重定向到登录页,认证完成后返回原页面执行POST操作。

原因分析

  1. OIDC回调方法限制:微软身份认证的OpenID Connect(OIDC)流程默认仅支持GET方法回调。当POST请求触发认证挑战时,认证完成后系统会尝试用POST方法回调原Action,若原Action仅配置为接收POST(或路由不匹配该方法),则触发405方法不允许错误。
  2. 默认认证Scheme配置错误:代码中默认认证Scheme设置为OpenIdConnectDefaults.AuthenticationScheme,导致挑战流程直接走OIDC,未通过Cookie认证中间层保存POST请求上下文,回调时无法正确恢复原请求的方法和参数。
  3. 日志中IDX21305和IDX21310提示回调时缺少code和access_token,本质是POST请求上下文未被正确持久化,导致认证流程无法完成正常回调。

解决方案

方案1:调整认证方案默认配置

将默认认证Scheme改为Cookie,把OIDC作为外部认证方案,让Cookie认证处理请求上下文的保存与恢复:

// 将默认认证Scheme改为Cookie
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
    .AddCookie(); // 显式添加Cookie认证

// 保留原Cookie配置并修正Scheme名称
builder.Services.Configure<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
    options.ExpireTimeSpan = TimeSpan.FromMinutes(builder.Configuration.GetValue<double>("AzureAd:TimeoutInMinutes"));
    options.SlidingExpiration = true;
    options.Cookie.Name = "App.Cookie";
    options.AccessDeniedPath = "/UserAccess/Denied";
    // 确保ReturnUrl参数正确传递,回调时用GET方法恢复请求
    options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
});

方案2:自定义授权过滤器处理POST请求挑战

自定义AuthorizationFilter,拦截POST请求的认证挑战,将其重定向为GET请求到登录页,避免OIDC回调时的方法冲突:

public class PostAuthorizeFilter : AuthorizeFilter
{
    public PostAuthorizeFilter(IAuthorizationPolicyProvider policyProvider) : base(policyProvider)
    {
    }

    public override async Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        await base.OnAuthorizationAsync(context);

        // 如果是POST请求且未通过认证,重定向到登录页(用GET方法)
        if (context.Result is ChallengeResult && context.HttpContext.Request.Method == HttpMethods.Post)
        {
            var returnUrl = context.HttpContext.Request.Path + context.HttpContext.Request.QueryString;
            context.Result = new RedirectToActionResult("SignIn", "Account", new { ReturnUrl = returnUrl });
        }
    }
}

在Program.cs中替换原有的AuthorizeFilter:

builder.Services.AddControllersWithViews(options =>
{
    var policy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
    // 替换为自定义的PostAuthorizeFilter
    options.Filters.Add(typeof(PostAuthorizeFilter));
}).AddMicrosoftIdentityUI();

// 注册自定义过滤器的依赖
builder.Services.AddScoped<PostAuthorizeFilter>();

方案3:配置OIDC回调的方法兼容性

修改OIDC配置,强制回调时使用GET方法,同时确保原Action支持GET方法(业务允许的情况下):

builder.Services.Configure(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
    options.Events.OnTicketReceived = context =>
    {
        // 原有的用户验证逻辑
        return Task.CompletedTask;
    };
    // 强制回调使用GET方法
    options.ResponseType = OpenIdConnectResponseType.Code;
    options.GetClaimsFromUserInfoEndpoint = true;
});

验证

修改配置后重启应用:

  • 未登录状态下发起POST请求,会被重定向到微软认证页面。
  • 完成认证后,系统会正确跳转回原页面,用POST方法执行原Action,不再出现405错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 21:47:47