web-dev-qa-db-ja.com

ASP.NET Core CORS WebAPI:Access-Control-Allow-Originヘッダーなし

ASP.NET Core Web APIをAzureにデプロイしました。SwaggerまたはFiddlerなどのWebデバッガーを使用して、そのエンドポイントにアクセスできます。両方の場合(Swaggerの同じOrigin、コンピューターからFiddlerを使用する異なるOrigin)、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アプリは同じローカルホストの異なるポートにあるため、これはOrigin間で「true」になります(ここで見つけた提案のため、これをコメントしています: 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ヘッダーを返さないため、別のOriginでホストされているブラウザーベースのクライアントは失敗します。それでも、少なくとも上記のドキュメントから判断すると、CORSのセットアップは問題ないようです。私は真のクロスオリジン環境にいます。そして、私はミドルウェアを他のミドルウェアの前に置きます。たぶん私は明らかな何かを見逃しているかもしれませんが、これらの周りをグーグルで検索することは私が見つけたすべての推奨事項です。ヒントはありますか?

[〜#〜] update [〜#〜]

@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.
_
31
Naftis

コメントからコピーした自分自身の質問への回答を次に示します。AzureポータルにCORSセクションがあることに気付いていませんでした。そこで許可されたOriginを入力しないと、コードベースの設定はまったく関係ないように見えます。ここではURLを複製する必要があるため、これは奇妙に見えますが、*許可されたオリジンに対して、それは機能しました。

9
Naftis

.AllowAnyHeader()メソッドを追加すると問題が解決する可能性があります

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

エラーメッセージは非常に誤解を招くものです。 DbContextに新しいテーブルを追加しようとすると、同じエラーが発生しました。 Angularは「Access-Control-Allow-Origin」エラーを与えていませんでしたが、Postmanは500内部サーバーエラーを与えていました。_userManager.FindByEmailAsync()を呼び出そうとするとLoginメソッドが失敗しました。これが他の誰かに役立つことを願っています。

0
Dumber_Texan2