我在努力做什么
我有一个后台ASP。Net Core Web API托管在Azure免费计划上(源代码: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://learn.microsoft.com/en-us/aspnet/core/security/cors
我已经遵循微软网站上的本教程,尝试在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")
有了这个方法,跨站点的头被正确地应用,他们显示在我的开发控制台和邮差。然而问题是,当它通过Access-Control-Allow-Origin
检查时,web浏览器抛出了一个(我相信)Access-Control-Allow-Headers
声明415 (Unsupported Media Type)
所以暴力法也不管用
最后
有没有人得到了这个工作,可以伸出手来,或者只是能够指出我在正确的方向?
编辑
因此,为了让API调用通过,我不得不停止使用JQuery,并切换到纯Javascript XMLHttpRequest
格式。
尝试1
我设法让Microsoft.AspNetCore.Cors
通过遵循MindingData的答案工作,除了在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"));