我想要做什么
我有一个托管在 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中间件拒绝设置标头。
Microsoft.AspNetCore.Cors
我Microsoft.AspNetCore.Cors是通过 NUGET 安装的,版本是1.1.2
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")]每个控制器都这样
[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)
Access- Control-Allow-Origin
Access-Control-Allow-Headers``415 (Unsupported Media Type)
所以蛮力法也行不通
最后
有没有人让这个工作并且可以伸出援助之手,或者只是能够指出我正确的方向?
编辑
所以为了让 API 调用通过,我不得不停止使用 JQuery 并切换到纯 JavascriptXMLHttpRequest格式。
XMLHttpRequest
尝试 1
我设法Microsoft.AspNetCore.Cors通过遵循 MindingData 的回答来工作,除了在ConfigureMethod 中放置app.UseCorsbefore app.UseMvc。
Configure
app.UseCors
app.UseMvc
此外,当与options.AllowAnyOrigin()通配符支持的 Javascript API 解决方案混合时,它也开始起作用。
options.AllowAnyOrigin()
尝试 2
所以我设法让尝试 2(蛮力强制它)工作......唯一的例外是通配符Access-Control-Allow- Origin不起作用,因此我必须手动设置有权访问它的域。
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"));
因为你有一个非常简单的 CORS 策略(允许来自 XXX 域的所有请求),你不需要让它变得如此复杂。首先尝试执行以下操作(CORS 的一个非常基本的实现)。
如果您还没有,请安装 CORS nuget 包。
Install-Package Microsoft.AspNetCore.Cors
在您的 startup.cs 的 ConfigureServices 方法中,添加 CORS 服务。
public void ConfigureServices(IServiceCollection services) { services.AddCors(); // Make sure you call this previous to AddMvc services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
然后在您的 startup.cs 的配置方法中,添加以下内容:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { // Make sure you call this before calling app.UseMvc() app.UseCors( options => options.WithOrigins("http://example.com").AllowAnyMethod() ); app.UseMvc(); }
现在试一试。策略适用于您需要针对不同操作(例如不同主机或不同标头)的不同策略。对于您的简单示例,您确实不需要它。从这个简单的示例开始,然后根据需要进行调整。
进一步阅读:http ://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net- core/