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

ASP.NET Core MVC+VueJS SPA集成Azure AD认证:会话过期重定向问题

解决方案

问题根源

你遇到的CORS错误,本质是AJAX请求无法处理跨域重定向:当会话过期后,ASP.NET Core默认会返回302重定向到Azure AD登录页,但前端axios的跨域请求会被浏览器拦截,触发CORS错误。你之前修改OnRedirectToIdentityProvider无效,是因为重定向逻辑最先由Cookie认证中间件触发,而非OpenIdConnect中间件。

方案1:让API请求返回401(推荐)

针对AJAX请求返回401状态码,而非重定向,前端可通过拦截器统一处理跳转;非页面请求(如浏览器直接访问)仍保持重定向到自定义登录页。

修改Program.cs配置

在Cookie认证中间件的事件中添加判断逻辑:

builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(options =>
    {
        builder.Configuration.Bind("AzureAd", options);
        options.Events = new OpenIdConnectEvents
        {
            OnTokenValidated = context =>
            {
                // 保留你原有的UserID Claim添加逻辑
                string query = "select dbo.A2F_0013_ReturnUserIDForEmail(@Email) as UserID";
                string connectionString = builder.Configuration.GetValue<string>("ConnectionStrings:DBContext");
                string signInEmailAddress = context.Principal.FindFirstValue("preferred_username");

                using (var connection = new SqlConnection(connectionString))
                {
                    var queryResult = connection.QueryFirst(query, new { Email = signInEmailAddress });

                    var claims = new List<Claim>
                    {
                        new Claim("UserID", queryResult.UserID.ToString())
                    };

                    var appIdentity = new ClaimsIdentity(claims);
                    context.Principal.AddIdentity(appIdentity);
                }

                return Task.CompletedTask;
            },
        };
    })
    .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
    .AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
    .AddInMemoryTokenCaches()
    // 配置Cookie认证的重定向逻辑
    .AddCookie(options =>
    {
        options.Events.OnRedirectToLogin = context =>
        {
            // 判断是否为AJAX请求(可根据你的前端实际情况调整判断条件)
            bool isAjaxRequest = 
                context.Request.Headers["X-Requested-With"] == "XMLHttpRequest" ||
                context.Request.ContentType?.StartsWith("application/json") == true ||
                context.Request.Headers["Accept"]?.Contains("application/json") == true;

            if (isAjaxRequest)
            {
                // 返回401及自定义提示信息
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                context.Response.ContentType = "application/json";
                var errorMsg = JsonSerializer.Serialize(new { message = "登录已过期,请重新登录" });
                return context.Response.WriteAsync(errorMsg);
            }
            // 非AJAX请求,重定向到自定义登录页
            context.Response.Redirect("/Login");
            return Task.CompletedTask;
        };
    });

前端axios拦截器处理

在Vue项目中添加axios响应拦截器,捕获401状态码并跳转到自定义登录页:

axios.interceptors.response.use(
    response => response,
    error => {
        if (error.response?.status === 401) {
            window.location.href = '/Login';
        }
        return Promise.reject(error);
    }
);

方案2:统一重定向到自定义登录页

如果希望所有未认证请求都重定向到你的localhost/login页面(而非Azure AD直接登录页),只需确保自定义登录页包含Azure AD登录按钮,并调整Cookie认证的LoginPath:

1. 配置Cookie的LoginPath

在上述AddCookie配置中,直接设置LoginPath:

.AddCookie(options =>
{
    options.LoginPath = "/Login"; // 指向你的自定义登录页
    // 保留OnRedirectToLogin的AJAX判断逻辑(可选)
});

2. 自定义登录页添加Azure AD登录按钮

在/Login页面的Razor视图中,添加Microsoft Identity的登录组件:

@page
@{
    ViewData["Title"] = "登录";
}

<div class="login-container">
    <h1>请登录</h1>
    <a asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignIn" class="btn btn-primary">
        使用Azure AD登录
    </a>
</div>

关于CORS的说明

不需要配置CORS允许login.microsoft.com,这属于不良实践:重定向是浏览器端的跳转行为,不属于AJAX跨域请求范畴,配置CORS无法解决该问题,反而会引入不必要的安全风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 15:01:00