リクエストヘッダーフィールドAccess-Control-Allow-Headersは、プリフライトレスポンスでは単独では使用できません


234

CORSの問題に何度も遭遇し、通常は修正できますが、MEANスタックパラダイムからこれを見て本当に理解したいと思います。

これらのことをキャッチするためにエクスプレスサーバーにミドルウェアを単に追加する前に、私のリクエストをエラーアウトしているある種の事前フックがあるようです。

リクエストヘッダーフィールドAccess-Control-Allow-Headersは、プリフライトレスポンスのAccess-Control-Allow-Headersでは許可されていません

私はこれができると思いました:

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Headers","*")
})

または同等ですが、これはそれを修正していないようです。もちろん試しました

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Headers","Access-Control-Allow-Headers")
})

まだ運がない。

回答:


245

カスタムリクエストヘッダーをいじり始めると、CORSプリフライトが表示されます。これは、HTTP OPTIONS動詞を使用し、いくつかのヘッダーAccess-Control-Request-Headersを含むリクエストです。そのうちの1つは、クライアントがリクエストに含めたいヘッダーをリストしています。

これを機能させるには、適切なCORSヘッダーを使用してCORSプリフライトに返信する必要があります。その1つは確かAccess-Control-Allow-Headersです。そのヘッダーには、Access-Control-Request-Headersヘッダーと同じ値(またはそれ以上)を含める必要があります。

https://fetch.spec.whatwg.org/#http-cors-protocolで、この設定について詳しく説明しています。


41
Chromeを使用していて、どのヘッダーが要求されているかわからない場合は、開発者コンソールを使用して、ネットワークが行われている呼び出しを選択し、要求されているヘッダーを確認できますAccess-Control-Request-Headers
Lionel Morrison

5
Developer Consoleオプションは良いものです。サーバー上のリクエストオブジェクトにアクセスし、ヘッダーの値、特に「Access-Control-Request-Headers」のヘッダー値をダンプすることで、必要なものを見つけることもできます。次に、これをコピーしてresponse.setHeader( "Access-Control-Allow-Headers"、 "{paste here}")に貼り付けます
ソフトウェアの預言​​者

7
例をお願いします!
Demodave

5
@Demodaveは私のためにこれの例はheader("Access-Control-Allow-Headers: Content-Type")
Joshua Duxbury

1
@LionelMorrison、ヘッダーの照合にChrome開発ツールを使用。よく説明されました!!!
Savina Chandla 2017年

119

これは、それを機能させるために追加する必要があるものです。

response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
response.setHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");

ブラウザはプリフライト要求を送信し(メソッドタイプOPTIONSを使用)、サーバーでホストされているサービスが別のドメインのブラウザからアクセスできるかどうかを確認します。上記のヘッダーを挿入すると、プリフライトリクエストに応答して、ブラウザーはそれ以上の呼び出しを行っても問題がないことを理解し、実際のGET / POST呼び出しに対して有効な応答を取得します。*の代わりにAccess-Control-Allow-Origin "、" localhost、xvz.com "を使用して、アクセスが許可されるドメインを制限できます(*はすべてのドメインへのアクセスを許可します)


7
*for ...-Origintrueforを組み合わせることはできません...-Credentials。認証されていないリクエストに対しては失敗しませんが、認証されたリクエストに対しては機能しません。私の回答に投稿したリンクを参照してください。
Anne

Manish Aroraに感謝します。私のAPIであなたのソリューションを使用しましたが、うまくいきました。HttpContext.Response.Headers.Add( "Access-Control-Allow-Methods"、 "GET、HEAD、OPTIONS、POST、PUT"); HttpContext.Response.Headers.Add( "Access-Control-Allow-Headers"、 "Access-Control-Allow-Headers、Origin、Accept、X-Requested-With、Content-Type、Access-Control-Request-Method、Access -Control-Request-Headers "); HttpContext.Response.Headers.Add( "Access-Control-Allow-Origin"、 " localhost:4200");
Ramakrishnankt

1
これは、「プリフライト」のため、サーバー側でこのすべての応答ヘッダーの変更が必要であることを示していますか?どうして?特に完全に標準的なヘッダーの場合はどうでしょうか?しばらくHTTPを使用していたので、多くのボイラープレートが必要になるのは私にとってはニュースです。
サマンサアトキンス

@manish Access-Control-Allow-Headersに異なる値のセットがあり、機能しませんでした。あなたの値のセットはそうしました。時間とフラストレーションを節約してくれてありがとう。
azakgaim

一部のヘッダーをワイルドカード化する方法はありますか?すべてのヘッダーをワイルドカードにするのは悪い考えですか?などresponse.setHeader("Access-Control-Allow-Headers", "*")?これを行うことのセキュリティ上の意味は何ですか?
Vadorequest

78

この問題は

 "Origin, X-Requested-With, Content-Type, Accept, Authorization"

特に私のプロジェクト(express.js / nodejs)

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
  next();
});

更新:

毎回エラー:Access-Control-Allow-Headers is not allowed by itself in preflight responseエラーはChrome開発者ツールの何が問題かを確認できます
ここに画像の説明を入力してください

上記のエラーがないContent-Typeため、文字列Content-Typeを追加しますAccess-Control-Allow-Headers


1
これは誰にとってもうまくいきません。Access-Control-Request-Headersの値は、環境によって異なる場合があります。サーバー上のリクエストオブジェクトにアクセスし、「Access-Control-Request-Headers」ヘッダーの値をダンプします。次に、これをコピーしてresponse.setHeader( "Access-Control-Allow-Headers"、 "{paste here}")に貼り付けます
ソフトウェアの預言​​者

1
また、AuthorizationのスペルがBritshの方法ではなく、アメリカの方法であることを確認してください。それは私の人生の30分です。Thx USA![ため息]
ジオイデシック2018年

14

受け入れられた答えは大丈夫ですが、私はそれを理解するのが困難でした。これを明確にするための簡単な例を示します。

私のajaxリクエストには、標準のAuthorizationヘッダーがありました。

$$(document).on('ajaxStart', function(e){
var auth_token = localStorage.getItem(SB_TOKEN_MOBILE);
if( auth_token ) {
    var xhr = e.detail.xhr;

    xhr.setRequestHeader('**Authorization**', 'Bearer ' + auth_token);
}

このコードは問題のエラーを生成します。nodejsサーバーで私がしなければならなかったことは、許可されたヘッダーに承認を追加することでした:

res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,**Authorization**');

6

他の回答に追加します。私は同じ問題を抱えていましたが、これは私がエクスプレスサーバーでREST呼び出しを許可するために使用したコードです。

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', 'URLs to trust of allow');
  res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  if ('OPTIONS' == req.method) {
  res.sendStatus(200);
  } else {
    next();
  }
});

このコードが基本的に行うことは、すべてのリクエストをインターセプトし、CORSヘッダーを追加してから、通常のルートを続行することです。OPTIONSリクエストがある場合、CORSヘッダーのみで応答します。

編集:私は同じマシン上の2つの別々のnodejs Expressサーバーにこの修正を使用していました。最後に、単純なプロキシサーバーの問題を修正しました。


ありがとう!単純なプロキシサーバーの使用方法について詳しく教えてください。
austin_ce

5

私は自分でこの問題に遭遇しました。ASP.NETのコンテキストでは、Web.configが次のようになっていることを確認してください。

  <system.webServer>
<modules>
  <remove name="FormsAuthentication" />
</modules>

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <!--<remove name="OPTIONSVerbHandler"/>-->
  <remove name="TRACEVerbHandler" />
  <!--
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  -->
</handlers>

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Headers" value="Content-Type, Authorization" />
    <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
  </customHeaders>
</httpProtocol>

Access-Control-Allow-HeadersキーのAuthorization値に注意してください。Authorization値がありませんでした。この構成で問題が解決しました。


5

私はこれをsilexプロジェクトで使用しました

$app->after(function (Request $request, Response $response) {
        $response->headers->set('Access-Control-Allow-Origin', '*');
        $response->headers->set("Access-Control-Allow-Credentials", "true");
        $response->headers->set("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
        $response->headers->set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
    });

2
このコードは質問に答えることがありますが、問題を解決する方法や理由に関する追加のコンテキストを提供すると、回答の長期的な価値が向上します。
Badacadabra 2017年

4

Chromeの場合:

リクエストヘッダーフィールドX-Requested-Withは、プリフライトレスポンスのAccess-Control-Allow-Headersでは許可されていません。

私にとって、このエラーは、この呼び出しのURLの末尾のスペースによって引き起こされまし

jQuery.getJSON( url, function( response, status, xhr ) {
   ...
}

3

追加するだけで、これらのヘッダーをWebpack構成ファイルにも配置できます。私はwebpack開発サーバーを実行していたので、私の場合と同様にそれらを必要としました。

devServer: {
    headers: {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Credentials": "true",
      "Access-Control-Allow-Methods": "GET,HEAD,OPTIONS,POST,PUT",
      "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept, Authorization"
},


2

OPがDjango、React、およびdjango-cors-headers libを使用して述べたエラーを受け取りました。このスタックで修正するには、次のようにします。

settings.pyに、公式ドキュメントに従って以下を追加します。

from corsheaders.defaults import default_headers

CORS_ALLOW_HEADERS = default_headers + (
'YOUR_HEADER_NAME',
)

2

この問題は、リクエストにカスタムヘッダーを作成したときに発生しHTTP OPTIONSます。

この要求に必要なヘッダーはです。これAccess-Control-Request-Headersは応答ヘッダーの一部であり、すべての発信元からの要求を許可する必要があります。時にはそれはContent-Type同様に応答のヘッダーに必要です。だからあなたの応答ヘッダーはそのようなものでなければなりません-

response.header("Access-Control-Allow-Origin", "*"); // allow request from all origin
response.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
response.header("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin, X-Requested-With, Content-Type, Accept, Authorization");

1

Post API呼び出しでは、リクエスト本文でデータを送信しています。したがって、API呼び出しに追加のヘッダーを追加してデータを送信する場合。次に、最初のOPTIONS API呼び出しが発生し、次にpost呼び出しが発生します。したがって、最初にOPTION API呼び出しを処理する必要があります。

フィルターを作成することで問題を処理でき、その中でオプション呼び出しAPI呼び出しを確認して200 OKステータスを返す必要があります。以下はサンプルコードです:

package com.web.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.connector.Response;

public class CustomFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest httpRequest = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type");
        if (httpRequest.getMethod().equalsIgnoreCase("OPTIONS")) {
            response.setStatus(Response.SC_OK);
        }
        chain.doFilter(req, res);
    }

    public void init(FilterConfig filterConfig) {
        // TODO
    }

    public void destroy() {
        // Todo
    }

}

1

リクエストヘッダーにカスタムヘッダーを追加する場合は、特定のヘッダーの実行が許可されていることをサーバーに通知する必要があります。それを行う場所は、リクエストをフィルタリングするクラスです。以下の例では、カスタムヘッダー名は「type」です。

public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin",  request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,PATCH,OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me, Authorization, type ");
        response.setHeader("Access-Control-Expose-Headers","Authorization");
    }
}

1

ほぼ1日を過ごした後、以下の2つのコードを追加すると問題が解決することがわかりました。

これをGlobal.asaxに追加します

protected void Application_BeginRequest()
{
  if (Request.HttpMethod == "OPTIONS")
  {
    Response.StatusCode = (int)System.Net.HttpStatusCode.OK;             
    Response.End();
  }
}

そしてウェブ設定で以下を追加します

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />        
    <add name="Access-Control-Allow-Methods" value="*" />
    <add name="Access-Control-Allow-Headers" value="Content-Type, Authorization" />
  </customHeaders>
</httpProtocol>

1

私もAngular 6で同じ問題に直面しました。以下のコードを使用して問題を解決しました。component.tsファイルにコードを追加します。

import { HttpHeaders } from '@angular/common/http';

headers;

constructor() {
    this.headers = new HttpHeaders();
    this.headers.append('Access-Control-Allow-Headers', 'Authorization');
}

getData() {
    this.http.get(url,this.headers). subscribe (res => {
    // your code here...
})}

0

私が直面していた同じ問題。

簡単な変更を行いました。

  <modulename>.config(function($httpProvider){
    delete $httpProvider.defaults.headers.common['X-Requested-With'];
});

0

APIでは「認証」が許可されていないことを示すメッセージは明らかです。セット
アクセス制御-許可-ヘッダ: "Content-Typeの、認可"


0
const express = require('express')
const cors = require('cors')
const app = express()

app.get('/with-cors', cors(), (req, res, next) => {
  res.json({ msg: 'WHOAH with CORS it works! 🔝 🎉' })
})

get関数にcorsを追加することは私にとってうまくいきました

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.