如何修复 CORS 策略以防止 AJAX 调用在 MVC Core 3.1 中使用 [Authorize] 属性?

Posted

技术标签:

【中文标题】如何修复 CORS 策略以防止 AJAX 调用在 MVC Core 3.1 中使用 [Authorize] 属性?【英文标题】:How to fix CORS policy preventing AJAX calls from using [Authorize] attribute in MVC Core 3.1? 【发布时间】:2021-07-03 12:05:23 【问题描述】:

我在 ASP.NET MVC Core 3.1 应用程序中实现身份验证和授权。我有 [Authorize] 在我的操作中指定角色。其中一些操作由 AJAX 调用,只要用户保持身份验证,它们就可以正常工作。即使用户没有访问由 AJAX 调用的操作的角色,我也可以在我的全局 AJAX 错误处理程序中捕获 http 状态代码 403 并将它们重定向到未授权页面:

$(document).ajaxError(function (event, xhr, ajaxSettings, thrownError) 
    if (xhr.status == 403) 
        window.location = "/UserAccess/NotAuthorized";
    
);

但是,如果我从应用程序中退出,然后尝试运行通过 AJAX 调用的操作,我会在控制台中收到以下错误:

从源“https://”访问“https://login.microsoftonline.com/.......”处的 XMLHttpRequest(从“https://localhost:44319/Mfgrs/GetEditMfgrPartialView”重定向) localhost:44319' 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。

前端没有发生任何事情,我不会被重定向到页面以重新验证我的身份,就像正常请求操作时那样(不使用 AJAX,只需通过常规表单提交)。我什至没有得到401 的状态,所以我至少可以将用户重定向到登录页面。状态只是0,所以它没有告诉我发生了什么。

我知道有很多关于 AJAX 的 CORS 政策问题的问题,但我无法解决任何问题。我尝试了Microsoft docs 中列出的不同解决方案,以及一些来自*** 的解决方案。我最终找到了this article,上面写着:

某些 CORS 问题无法解决,例如当您的应用重定向到 login.microsoftonline.com 进行身份验证,以及访问令牌 过期。然后 CORS 调用失败。这种情况的解决方法是 延长访问令牌的生命周期,以防止它 在用户会话期间过期。

我不想做的是实现自定义授权属性,因为我不相信它会那么安全。如果没有出现 CORS 问题,我什至不能从 AuthorizeAttribute 继承。此外,根据this thread,Microsoft 建议永远不要创建自己的解决方案。

我的问题是,如何让 [Authorize] 属性与 AJAX 调用一起使用?处理这个问题的正确方法是什么?没有自定义属性也可以吗?

我通过 AJAX 调用的一个简单操作:

[Authorize(Roles = "ADMIN, MANAGER")]
[HttpGet]
public IActionResult GetAddMfgrPartialView()

    return PartialView("_AddMfgrPartial");

Startup.cs 配置方法:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

    app.UseDeveloperExceptionPage();

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthentication(); // who are you?            
    app.UseAuthorization(); // are you allowed?

    app.UseEndpoints(endpoints =>
    
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "controller=UserAccess/action=Index/id?");
    );


【问题讨论】:

我不确定您的问题是否完全是 CORS,因为您在登录时能够进行 AJAX 调用。当发出匿名请求时,更有可能在 MVC 管道的某处引发异常由于缺乏异常处理,这会导致浏览器出现此 CORS 消息。也许您应该尝试添加一些异常中间件docs.microsoft.com/en-us/aspnet/core/fundamentals/… 并从那里开始调查问题。 您能发布您的Startups.Configure 方法(您的中间件管道)吗? 感谢您的评论。实际上,我确实添加了 app.UseDeveloperExceptionPage(); 中间件,它并没有像往常一样处理异常。另外,我认为我在登录时可以进行 AJAX 调用的原因是因为它们都指向应用程序的网站。当我退出时,[Authorize] 属性会尝试重定向到 https://login.microsoftonline.com/ 以尝试重新验证。 @Pieterjan 请看我编辑的帖子。 只是猜测...可以修改以下中间件的顺序再试一次吗? UseAuthentication、UseRouting、UseAuthorization、UseEndpoints 【参考方案1】:

时间限制要求我想出某种解决方案,我可以在 AJAX 调用的操作上使用 [Authorize] 属性。解决方案是将 AJAX 全局错误处理程序修改为以下内容:

$(document).ajaxError(function (event, xhr, ajaxSettings, thrownError) 
    //403 code returned from [Authorize] filter when user is authenticated but does not have permissions
    if (xhr.status == 403) 
        window.location = "/UserAccess/NotAuthorized";
     else if (xhr.status == 0)  //else, we assume status 0 probably means user is unauthenticated and we have the CORS policy issue: https://***.com/q/66990101/12300287
        window.location = "/Error/Unknown"; //redirect user the Unknown error page, suggesting them to sign-in.
    
);

如果返回的 http 状态代码为 0,我会将用户重定向到一个错误页面,指出发生了错误并建议他们登录。这只是一个建议,因为状态码 0 可能由于许多其他原因而发生。

我还发现了一些有用的 SO 帖子,可以帮助那些想要更好解决方案的人: https://***.com/a/64341476/12300287

https://***.com/a/65494627/12300287

https://***.com/a/37812311/12300287

【讨论】:

以上是关于如何修复 CORS 策略以防止 AJAX 调用在 MVC Core 3.1 中使用 [Authorize] 属性?的主要内容,如果未能解决你的问题,请参考以下文章

发出 POST 请求时如何防止触发 CORS? [复制]

球衣后端 jquery AJAX API 调用中的 Cors 策略阻塞

ajax 查询中 Java + Spring 的 CORS 策略错误

同源策略与 CORS 的用处

如何修复 XMLHttpRequest 已被 CORS 策略阻止

如何防止 CORS 策略阻止从本地主机到第三方 API 的请求?