【问题标题】:ASP.NET Core CORS WebAPI: no Access-Control-Allow-Origin headerASP.NET Core CORS WebAPI:没有 Access-Control-Allow-Origin 标头
【发布时间】:2017-04-15 23:47:28
【问题描述】:

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

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

  2. 将中间件添加到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


【解决方案1】:

WebApi Project ---> 右键单击​​ References ---> 在 Manage Nuget Packages 部分中搜索 Core。通过安装将 Microsoft.AspNet.WebApi.Cors 添加到项目中

将以下代码添加到项目中App_Start文件夹下的WebApi.Config文件中。

var cors = new EnableCorsAttribute("","","*"); config.EnableCors(cors);

enter image description here

enter image description here

【讨论】:

  • OP 询问的是 ASP.NET CORE,而不是 ASP.NET
【解决方案2】:

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

【讨论】:

  • 对于感兴趣的读者,这是一个更新的使用 OpenIdDict rc 3 的密码流的最小示例,它进行了一些 API 更改:github.com/Myrmex/oid-credentials。注意 [Authorize] 属性参数(readme 中的尾注)。
  • 我没有测试过,但如果这是真的,那么在代码中配置 CORS 有什么意义?感谢 Naftis 指出:)
  • 您为我节省了数小时的故障排除时间!谢谢!我很欣赏 MS 允许在 Azure 门户中进行 CORS 配置,但令人沮丧的是它并不明显。这似乎完全覆盖了基于代码的 CORS 配置(正如其他人所说)......
  • 这个没必要,你可以用app.UseCors
  • 我在允许的来源中添加了 *,但现在我的 POST 请求在我的 Angular 应用程序和 Postman 测试中都会产生 500 个错误
【解决方案3】:

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

app.UseCors(builder => builder.WithOrigins("http://localhost:4200")
                              .AllowAnyMethod()
                              .AllowAnyHeader());

【讨论】:

    【解决方案4】:

    错误信息非常具有误导性。尝试将新表添加到 DbContext 后,我​​遇到了同样的错误。 Angular 没有给出“Access-Control-Allow-Origin”错误,但 Postman 给出了 500 Internal Server 错误。尝试调用 _userManager.FindByEmailAsync() 时登录方法失败。希望这对其他人有帮助。

    【讨论】:

      【解决方案5】:

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

        app.UseRouting();
        app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
        app.UseEndpoints(endpoints => .....
      

      【讨论】:

      • 谢谢!这个小费结束了几个小时的挠头和酗酒!
      • 恭喜!我已经尝试了一切,但那一点救了我
      猜你喜欢
      • 2019-12-07
      • 2020-08-30
      • 1970-01-01
      • 2019-10-03
      • 2018-08-30
      • 2016-05-13
      • 2018-09-19
      • 2019-06-19
      • 2014-01-20
      相关资源
      最近更新 更多