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

ASP.NET Core 3.1 Cookie授权:Ajax调用未跳转登录页问题排查

问题分析与解决方案

这个问题的核心在于浏览器对Ajax请求的401未授权响应的默认行为:当XMLHttpRequest/fetch这类异步请求收到401状态码时,浏览器会自动弹出凭证输入弹窗(如果你的服务器同时启用过Windows身份验证,这种表现会更明显),而不是像普通页面请求那样自动触发跳转登录页的逻辑。

你的Cookie授权配置和用户验证逻辑本身是符合微软规范的,但缺少了对Ajax请求的特殊响应处理。

解决步骤

1. 修改Cookie授权事件,区分Ajax与普通请求

在AddCookie的配置中,新增OnRedirectToLogin事件处理,判断当前请求是否为Ajax请求:如果是,直接返回401状态码而非跳转;如果是普通页面请求,则执行默认的跳转登录页逻辑。

修改后的Cookie授权配置代码如下:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(co => {
        co.LoginPath = @$"/{ControllerHelpers.GetControllerName<AuthenticationController>()}/{nameof(AuthenticationController.Login)}";
        co.LogoutPath = @$"/{ControllerHelpers.GetControllerName<AuthenticationController>()}/{nameof(AuthenticationController.Logout)}";
        co.ExpireTimeSpan = TimeSpan.FromDays(30);
        co.Cookie.SameSite = SameSiteMode.Strict;
        co.Cookie.Name = "GioBQADashboard";
        co.Events = new CookieAuthenticationEvents 
        { 
            OnValidatePrincipal = UserPrincipalValidator.ValidateAsync,
            // 新增Ajax请求特殊处理
            OnRedirectToLogin = context =>
            {
                // 通过请求头判断是否为Ajax请求
                if (context.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
                {
                    // 对Ajax请求返回401状态码,不触发跳转
                    context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                    return Task.CompletedTask;
                }
                // 普通页面请求执行默认跳转逻辑
                return context.Response.Redirect(context.RedirectUri);
            }
        };
        co.Validate();
    });

2. 前端统一处理Ajax请求的401响应

在你的前端请求封装逻辑中(比如jQuery的全局配置、fetch拦截器),添加对401状态码的监听,一旦收到该响应,就主动跳转到登录页。

举个jQuery的示例:

$.ajaxSetup({
    complete: function(xhr) {
        if (xhr.status === 401) {
            window.location.href = "/Authentication/Login";
        }
    }
});

如果使用现代fetch API,可以这样添加拦截器:

const originalFetch = window.fetch;
window.fetch = async function(...args) {
    const response = await originalFetch(...args);
    if (response.status === 401) {
        window.location.href = "/Authentication/Login";
    }
    return response;
};

补充说明

  • 关于输入凭证后Windows身份保持登录的问题:如果你的服务器没有禁用Windows身份验证,当用户在弹窗中输入Windows凭证时,浏览器会自动发送Windows身份验证头部,ASP.NET Core会优先采用该验证方式让用户登录。如果不需要Windows身份验证,建议在项目中禁用它;如果需要保留,确保Cookie身份验证的优先级高于Windows身份验证。
  • 你现有的RejectUser方法逻辑是正确的,RejectPrincipal()和SignOutAsync()的调用顺序无需调整。

经过以上处理后,无论是普通页面请求还是Ajax请求,在用户被封禁后都会统一跳转到登录页,不会再弹出不必要的凭证输入弹窗。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 19:27:38