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

ASP.NET Core 7中如何允许被CORS策略阻止的重定向?

问题原因

你遇到的CORS错误核心在于:浏览器对预检OPTIONS请求的限制——预检请求不允许被重定向。当你的API接口触发认证挑战返回302重定向到登录页时,浏览器会拦截这个重定向并抛出CORS错误,因为预检请求的响应必须是2xx状态码,不能是302。

你的测试场景里,/api/ITodosApi/getTodos接口触发了重定向到谷歌,而前端是AJAX请求,浏览器先发送OPTIONS预检请求,这个请求被重定向后就触发了报错。

解决步骤

1. 调整认证逻辑:区分AJAX请求与普通浏览器请求

对于AJAX请求(比如前端SPA的API调用),不要返回302重定向,而是返回401未授权状态码,让前端主动处理跳转;仅对普通浏览器的页面请求返回302重定向到登录页。

在ASP.NET Core的认证配置中,可以通过CookieAuthenticationEvents实现这个判断:

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(fun opts ->
        opts.Events.OnRedirectToLogin <- fun context ->
            // 判断是否是AJAX请求
            if context.Request.Headers.ContainsKey("X-Requested-With") || 
               context.Request.Headers.Accept.ToString().Contains("application/json") then
                // 返回401,让前端处理跳转
                context.Response.StatusCode <- 401
                Task.CompletedTask
            else
                // 普通请求,执行默认重定向逻辑
                context.Response.Redirect(context.RedirectUri)
                Task.CompletedTask
        ) |> ignore

2. 修正CORS中间件的顺序

CORS中间件必须放在认证和授权中间件之前,否则预检请求会先被认证逻辑拦截重定向,导致CORS配置失效。调整代码顺序:

builder.Services.AddCors() |> ignore
builder.Services.AddAuthentication(...) // 先配置认证服务
builder.Services.AddAuthorization(...) // 再配置授权服务

let app = builder.Build()

// 中间件顺序必须遵循:UseCors -> UseAuthentication -> UseAuthorization -> UseEndpoints
app.UseCors(fun opts ->
    opts.WithOrigins("http://localhost:8080")
        .AllowCredentials()
        .AllowAnyMethod()
        .AllowAnyHeader() |> ignore
) |> ignore

app.UseAuthentication() |> ignore
app.UseAuthorization() |> ignore

app.UseEndpoints(fun endpoints ->
    endpoints.MapControllers() |> ignore
) |> ignore

3. 前端处理401状态码

当前端API请求收到401响应时,手动跳转到登录页(测试阶段可先跳转到谷歌,后续替换为Azure AD授权端点)。以Fable/Elmish为例:

// 示例:API调用的错误处理逻辑
let getTodos () =
    async {
        try
            let! todos = Http.get "/api/ITodosApi/getTodos"
            return Ok todos
        with
        | :? HttpException as ex when ex.StatusCode = 401 ->
            // 跳转到登录页
            Browser.Dom.window.location.href <- "https://accounts.google.com/"
            return Error "未授权,请登录"
        | ex ->
            return Error ex.Message
    }
关键说明
  • 预检请求是浏览器自动发送的OPTIONS请求,用于确认跨域请求是否被允许,这个请求不能被重定向,必须返回2xx状态码。
  • 让AJAX请求返回401而非302,是SPA应用处理认证的标准模式,可彻底避免这类CORS冲突。

内容的提问来源于stack exchange,提问作者Marko Grdinić

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 00:04:53