【发布时间】:2021-12-30 09:59:00
【问题描述】:
我要做什么
我有一个托管在 Azure 免费计划上的后端 ASP.Net Core Web API(源代码:https://github.com/killerrin/Portfolio-Backend)。
我还有一个客户网站,我想让它使用该 API。客户端应用程序不会托管在 Azure 上,而是托管在 Github Pages 或我有权访问的另一个 Web 托管服务上。因此,域名不会排队。
考虑到这一点,我需要在 Web API 端启用 CORS,但是我已经尝试了几个小时几乎所有的东西,但它拒绝工作。
我如何设置客户端 它只是一个用 React.js 编写的简单客户端。我在 Jquery 中通过 AJAX 调用 API。 React 网站可以正常工作,所以我知道不是这样。 Jquery API 调用正如我在尝试 1 中确认的那样工作。这是我进行调用的方式
var apiUrl = "http://andrewgodfroyportfolioapi.azurewebsites.net/api/Authentication";
//alert(username + "|" + password + "|" + apiUrl);
$.ajax({
url: apiUrl,
type: "POST",
data: {
username: username,
password: password
},
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
var authenticatedUser = JSON.parse(response);
//alert("Data Loaded: " + authenticatedUser);
if (onComplete != null) {
onComplete(authenticatedUser);
}
},
error: function (xhr, status, error) {
//alert(xhr.responseText);
if (onComplete != null) {
onComplete(xhr.responseText);
}
}
});
我的尝试
尝试 1 - “正确”的方式
https://docs.microsoft.com/en-us/aspnet/core/security/cors
我已按照 Microsoft 网站上的本教程进行操作,尝试了在 Startup.cs 中全局启用它的所有 3 个选项,在每个控制器上设置它并在每个操作上尝试它。
按照这种方法,跨域工作,但仅在单个控制器上的单个操作上工作(POST 到 AccountController)。对于其他所有内容,Microsoft.AspNetCore.Cors 中间件拒绝设置标头。
我通过NUGET安装了Microsoft.AspNetCore.Cors,版本是1.1.2
这是我在 Startup.cs 中的设置方式
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add Cors
services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
// Add framework services.
services.AddMvc();
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new CorsAuthorizationFilterFactory("MyPolicy"));
});
...
...
...
}
// This method gets called by the runtime. Use this method to configure
//the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
// Enable Cors
app.UseCors("MyPolicy");
//app.UseMvcWithDefaultRoute();
app.UseMvc();
...
...
...
}
如您所见,我正在按照指示做所有事情。我两次都在 MVC 之前添加了 Cors,当这不起作用时,我尝试将 [EnableCors("MyPolicy")] 放在每个控制器上
[Route("api/[controller]")]
[EnableCors("MyPolicy")]
public class AdminController : Controller
尝试 2 - 暴力破解
https://andrewlock.net/adding-default-security-headers-in-asp-net-core/
在尝试上一次尝试几个小时后,我想我会尝试通过手动设置标题来强制它,强制它们在每个响应上运行。我在本教程之后执行了此操作,该教程介绍了如何为每个响应手动添加标头。
这些是我添加的标题
.AddCustomHeader("Access-Control-Allow-Origin", "*")
.AddCustomHeader("Access-Control-Allow-Methods", "*")
.AddCustomHeader("Access-Control-Allow-Headers", "*")
.AddCustomHeader("Access-Control-Max-Age", "86400")
这些是我尝试过的其他标头,但失败了
.AddCustomHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE")
.AddCustomHeader("Access-Control-Allow-Headers", "content-type, accept, X-PINGOTHER")
.AddCustomHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Host, User-Agent, Accept, Accept: application/json, application/json, Accept-Language, Accept-Encoding, Access-Control-Request-Method, Access-Control-Request-Headers, Origin, Connection, Content-Type, Content-Type: application/json, Authorization, Connection, Origin, Referer")
使用此方法,跨站点标头被正确应用,它们显示在我的开发者控制台和 Postman 中。然而问题是,当它通过Access-Control-Allow-Origin 检查时,网络浏览器会在(我相信)Access-Control-Allow-Headers 上抛出一个嘶嘶声,声明415 (Unsupported Media Type)
所以蛮力法也行不通
终于
有没有人让这个工作并且可以伸出援助之手,或者只是能够指出我正确的方向?
编辑
为了让 API 调用通过,我不得不停止使用 JQuery 并切换到纯 Javascript XMLHttpRequest 格式。
尝试 1
我设法按照 MindingData 的回答让Microsoft.AspNetCore.Cors 工作,除了在Configure 方法中将app.UseCors 放在app.UseMvc 之前。
此外,当与用于通配符支持的 Javascript API 解决方案 options.AllowAnyOrigin() 混合时也开始起作用。
尝试 2
所以我设法让尝试 2(蛮力强制它)工作......唯一的例外是 Access-Control-Allow-Origin 的通配符不起作用,因此我必须手动设置有权访问的域它。
这显然不理想,因为我只是希望这个 WebAPI 向所有人广泛开放,但它至少在一个单独的站点上对我有用,这意味着它是一个开始
app.UseSecurityHeadersMiddleware(new SecurityHeadersBuilder()
.AddDefaultSecurePolicy()
.AddCustomHeader("Access-Control-Allow-Origin", "http://localhost:3000")
.AddCustomHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PUT, PATCH, DELETE")
.AddCustomHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Content-Type, Authorization"));
【问题讨论】:
-
对于您的
415 (Unsupported Media Type)问题,将Content-Type请求标头设置为application/json。 -
感谢您花时间写一个如此描述性的问题。
-
如果您使用 Postman 进行测试,请确保将请求标头的 Origin 设置为 * 或其他内容,然后尝试 #1 应该可以工作。没有这个头,Access-Control-Allow-Origin 将不会在响应头中返回。
-
下面关于 XMLHttpRequest 的评论帮我做了,谢谢!
-
我也在为同样的事情苦苦挣扎。从昨天开始。我也试图使用我的自定义中间件来强制它。真是头疼
标签: c# rest asp.net-core cors cross-domain