如何修复 CORS 策略以防止 AJAX 调用在 MVC Core 3.1 中使用 [Authorize] 属性?
How to fix CORS policy preventing AJAX calls from using [Authorize] attribute in MVC Core 3.1?
我正在 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 调用的操作,我会在控制台中收到以下错误:
Access to XMLHttpRequest at 'https://login.microsoftonline.com/.......' (redirected from 'https://localhost:44319/Mfgrs/GetEditMfgrPartialView') from origin 'https://localhost:44319' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
前端没有发生任何事情,我也没有被重定向到页面以重新验证我,就像我正常请求操作一样(不使用 AJAX,只是通过常规表单提交).我什至没有得到状态 401
所以我至少可以将用户重定向到登录页面。状态只是 0
,所以它没有告诉我发生了什么。
我知道有很多关于 AJAX 的 CORS 策略问题的问题,但我无法解决任何问题。我尝试了 Microsoft docs, and a few from Whosebug. I ended up finding this article 中列出的不同解决方案,上面写着:
Some CORS issues can't be resolved, such as when your app redirects to
login.microsoftonline.com to authenticate, and the access token
expires. The CORS call then fails. A workaround for this scenario is
to extend the lifetime of the access token, to prevent it from
expiring during a user’s session.
我不想做的是实施自定义授权属性,因为我不相信它会如此安全。如果没有出现 CORS 问题,我什至无法从 AuthorizeAttribute
继承。此外,根据 ,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?}");
});
}
时间限制要求我想出某种解决方案,我可以在 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:
window.location = "/Error/Unknown"; //redirect user the Unknown error page, suggesting them to sign-in.
}
});
如果 http 状态代码返回为 0,我会将用户重定向到一个错误页面,说明发生错误并建议他们登录。这只是一个建议,因为状态代码 0 可能由于许多其他原因而发生。
我还发现了一些有用的 SO 帖子,可以帮助那些想要更好解决方案的人:
我正在 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 调用的操作,我会在控制台中收到以下错误:
Access to XMLHttpRequest at 'https://login.microsoftonline.com/.......' (redirected from 'https://localhost:44319/Mfgrs/GetEditMfgrPartialView') from origin 'https://localhost:44319' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
前端没有发生任何事情,我也没有被重定向到页面以重新验证我,就像我正常请求操作一样(不使用 AJAX,只是通过常规表单提交).我什至没有得到状态 401
所以我至少可以将用户重定向到登录页面。状态只是 0
,所以它没有告诉我发生了什么。
我知道有很多关于 AJAX 的 CORS 策略问题的问题,但我无法解决任何问题。我尝试了 Microsoft docs, and a few from Whosebug. I ended up finding this article 中列出的不同解决方案,上面写着:
Some CORS issues can't be resolved, such as when your app redirects to login.microsoftonline.com to authenticate, and the access token expires. The CORS call then fails. A workaround for this scenario is to extend the lifetime of the access token, to prevent it from expiring during a user’s session.
我不想做的是实施自定义授权属性,因为我不相信它会如此安全。如果没有出现 CORS 问题,我什至无法从 AuthorizeAttribute
继承。此外,根据
我的问题是,如何让 [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?}");
});
}
时间限制要求我想出某种解决方案,我可以在 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:
window.location = "/Error/Unknown"; //redirect user the Unknown error page, suggesting them to sign-in.
}
});
如果 http 状态代码返回为 0,我会将用户重定向到一个错误页面,说明发生错误并建议他们登录。这只是一个建议,因为状态代码 0 可能由于许多其他原因而发生。
我还发现了一些有用的 SO 帖子,可以帮助那些想要更好解决方案的人: