【发布时间】:2017-04-15 23:47:28
【问题描述】:
我已将我的 ASP.NET Core Web API 部署到 Azure,我可以使用 Swagger 或 Fiddler 等 Web 调试器访问其端点。在这两种情况下(在 Swagger 中的相同来源,在我的计算机上使用 Fiddler 的不同来源),当访问 API 时,我得到了预期的结果,在我的Startup.cs 中启用了如下 CORS:
将
services.AddCors();添加到ConfigureServices。将中间件添加到
Configure:我知道这里的顺序很重要(ASP.NET 5: Access-Control-Allow-Origin in response),所以我将此调用放在方法的顶部,仅在日志或诊断中间件之前;这是我的完整方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory,
IDatabaseInitializer databaseInitializer)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
loggerFactory.AddNLog();
// to serve up index.html
app.UseDefaultFiles();
app.UseStaticFiles();
// http://www.talkingdotnet.com/aspnet-core-diagnostics-middleware-error-handling/
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
// CORS
// https://docs.asp.net/en/latest/security/cors.html
app.UseCors(builder =>
builder.WithOrigins("http://localhost:4200", "http://www.myclientserver.com")
.AllowAnyHeader()
.AllowAnyMethod());
app.UseOAuthValidation();
app.UseOpenIddict();
app.UseMvc();
databaseInitializer.Seed().GetAwaiter().GetResult();
env.ConfigureNLog("nlog.config");
// swagger
app.UseSwagger();
app.UseSwaggerUi();
}
localhost CORS 在开发过程中使用,指的是 Angular2 CLI 应用程序。 CORS 在本地运行良好,我的客户端和 API 应用程序位于同一个 localhost 的不同端口上,所以这是“真正的”跨源(我之所以这么说是因为我在这里找到的建议:https://weblog.west-wind.com/posts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas:作者该帖子注意到响应中的 CORS 标头仅在实际需要时发送,即在真正的跨域环境中)。
使用 Fiddler 我可以成功访问远程 API,但我得到 NO Access-Control-Allow-Origin 标头。因此,当从浏览器(通过我的客户端应用程序)调用 API 时,即使服务器返回 200,AJAX 请求也会失败。Fiddler 请求示例(成功):
GET http://mywebapisiteurl/api/values HTTP/1.1
User-Agent: Fiddler
回复:
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=3d551180c72208c1d997584c2b6119cf44e3a55c868f05ffc9258d25a58e95b1;Path=/;Domain=prinapi.azurewebsites.net
Date: Thu, 01 Dec 2016 10:30:19 GMT
["value1","value2"]
当尝试访问部署在 Azure 上的远程 API 时,我的客户端应用程序的 AJAX 请求总是失败并出现错误:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.myclientserver.com' is therefore not allowed access.
这是一个使用 Angular2(使用 Plunker)的示例客户端代码:
import {Component, NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import { Http, Headers, Response } from '@angular/http';
import { HttpModule } from '@angular/http';
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<button (click)="test()">test</button>
</div>
`,
})
export class App {
name:string;
constructor(private _http: Http) {
this.name = 'Angular2'
}
public test() {
this._http.get('http://theapisiteurlhere/api/values',
{
headers: new Headers({
'Content-Type': 'application/json'
})
})
.subscribe(
(data: any) => {
console.log(data);
},
error => {
console.log(error);
});
}
}
@NgModule({
imports: [ BrowserModule, HttpModule ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
总而言之,ASPNET API 服务器似乎没有返回预期的 CORS 标头,因此托管在不同来源的基于浏览器的客户端失败。然而,至少从上面引用的文档来看,CORS 设置似乎还可以;我处于真正的跨域环境中;我将中间件放在其他中间件之前。也许我遗漏了一些明显的东西,但是围绕这些谷歌搜索是我发现的所有建议。有什么提示吗?
更新
回复@Daniel J.G:来自提琴手的请求/响应成功:
GET http://theapiserver/api/values HTTP/1.1
User-Agent: Fiddler
Host: theapiserver
Origin: http://theappserver/apps/prin
和:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
Access-Control-Allow-Origin: http://theappserver/apps/prin
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=3d551180c72208c1d997584c2b6119cf44e3a55c868f05ffc9258d25a58e95b1;Path=/;Domain=theapiserver
Date: Thu, 01 Dec 2016 14:15:21 GMT
Content-Length: 19
["value1","value2"]
据报道,来自 Angular2 (Plunker) 的请求/响应反而失败了。通过检查网络流量,我只能看到预检请求:
OPTIONS http://theapiserver/api/values HTTP/1.1
Host: theapiserver
Proxy-Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://run.plnkr.co
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36
Access-Control-Request-Headers: content-type
Accept: */*
Referer: http://run.plnkr.co/h17wYofXGFuTy2Oh/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,it;q=0.6
HTTP/1.1 204 No Content
Server: Microsoft-IIS/8.0
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=3d551180c72208c1d997584c2b6119cf44e3a55c868f05ffc9258d25a58e95b1;Path=/;Domain=theapiserver
Date: Thu, 01 Dec 2016 14:23:02 GMT
此后,请求失败,不再有流量进入服务器。报告的问题是Response to preflight request doesn't pass access control check,同样是因为响应中缺少标头:
XMLHttpRequest cannot load http://theapiserver/api/values. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://run.plnkr.co' is therefore not allowed access.
【问题讨论】:
-
您是否尝试过在 fiddler 中设置主机和源头(主机到 api 主机,源到另一个以模拟跨源)?如果您发布由 Angular 提出的请求的详细信息,它也可能会有所帮助。
-
谢谢,我更新了我的帖子(见底部)。总之,使用 Fiddler 就可以了;使用 Angular2,预检请求失败,因为服务器响应中没有 ACAO 标头,尽管启用了 CORS。
-
您确定来源
http://run.plnkr.co是允许的来源之一吗? -
伙计们,找到了解决方案:我没有注意到 Azure 门户中有一个 CORS 部分。如果我没有在那里输入任何允许的来源,我的基于代码的配置似乎完全无关紧要。这对我来说看起来很奇怪,因为我不得不在这里复制 URL,但是一旦我将 * 添加到允许的来源,它就起作用了。
-
我猜 Azure 位于您的应用程序前面并进行自己的 CORS 检查
标签: c# azure angular asp.net-core cors