ASP.NET Core CORS WebAPI:没有Access-Control-Allow-Origin标头

Naf*_*tis 31 c# azure cors asp.net-core angular

我已将ASP.NET核心Web API部署到Azure,我可以使用Swagger或像Fiddler这样的Web调试器访问其端点.在这两种情况下(Swagger中的相同来源,使用来自我的计算机的Fiddler的不同来源),当访问API时,我得到了预期的结果,在我的下面启用了CORS Startup.cs:

  1. 添加services.AddCors();ConfigureServices.

  2. 将中间件添加到Configure:我知道这里的顺序很重要(ASP.NET 5:响应中的Access-Control-Allow-Origin),所以我将此调用放在方法的顶部,只是在记录或诊断中间件之前; 这是我的完整方法:


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();
}
Run Code Online (Sandbox Code Playgroud)

localhostCORS是开发过程中使用,并指Angular2 CLI应用程序.CORS在本地工作正常,我的客户端和API应用程序位于同一个本地主机上的不同端口上,所以这是"真正的"交叉起源(我正在评论这个,因为我在这里找到的建议:https://weblog.west -wind.com/windts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas:帖子的作者注意到响应中的CORS头在实际需要时发送,即在真正的跨源环境中).

使用Fiddler我可以成功访问远程API,但我没有Access-Control-Allow-Origin头.因此,当从浏览器(通过我的客户端应用程序)调用API时,即使服务器返回200,AJAX请求也会失败.示例Fiddler请求(成功):

GET http://mywebapisiteurl/api/values HTTP/1.1
User-Agent: Fiddler
Run Code Online (Sandbox Code Playgroud)

响应:

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"]
Run Code Online (Sandbox Code Playgroud)

当尝试访问部署在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.
Run Code Online (Sandbox Code Playgroud)

以下是使用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 {}
Run Code Online (Sandbox Code Playgroud)

总而言之,似乎ASPNET API服务器没有返回预期的CORS头,因此我托管在不同源上的基于浏览器的客户端失败.然而,CORS设置似乎没问题,至少从上面引用的文档判断; 我处在真正的跨性别环境中; 我把中间件放在其他人之前.也许我错过了一些明显的东西,但谷歌搜索这些是我发现的所有建议.任何提示?

UPDATE

回复@Daniel JG:来自fiddler的请求/回复是成功的:

GET http://theapiserver/api/values HTTP/1.1
User-Agent: Fiddler
Host: theapiserver
Origin: http://theappserver/apps/prin
Run Code Online (Sandbox Code Playgroud)

和:

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"]
Run Code Online (Sandbox Code Playgroud)

据报道,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
Run Code Online (Sandbox Code Playgroud)

此后,请求失败,没有更多流量进入服务器.报告的问题是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.
Run Code Online (Sandbox Code Playgroud)

Naf*_*tis 9

以下是我自己的问题的答案,从评论中复制:我没有注意到在Azure门户中有一个CORS部分.如果我没有在那里输入任何允许的来源,我的基于代码的配置似乎完全无关紧要.这对我来说很奇怪,因为我不得不在这里复制网址,但是一旦我添加*到允许的来源那里就可以了.

  • 你刚救了我几个小时的故障排除!谢谢!我很欣赏MS允许在Azure门户中进行CORS配置,但令人沮丧的是它并不是更明显.这似乎完全覆盖了基于代码的CORS配置(正如其他人所说的那样)...... (2认同)

kar*_*van 7

我遇到了类似的错误,但通过保持管道有序,我的错误得到了解决。(startup.cs -> configureServices) 就像

  app.UseRouting();
  app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
  app.UseEndpoints(endpoints => .....
Run Code Online (Sandbox Code Playgroud)


小智 6

添加 .AllowAnyHeader() 方法可以解决您的问题

app.UseCors(builder => builder.WithOrigins("http://localhost:4200")
                              .AllowAnyMethod()
                              .AllowAnyHeader());
Run Code Online (Sandbox Code Playgroud)