REST APIからデータを取得しようとしたときに、要求されたリソースに「Access-Control-Allow-Origin」ヘッダーが存在しません

625
daniel.lozynski 2017-05-10 03:47.

HPAlmのRESTAPIからいくつかのデータをフェッチしようとしています。小さなcurlスクリプトでかなりうまく機能します-データを取得します。

JavaScriptでそれを行うようになった今、フェッチとES6(多かれ少なかれ)はより大きな問題のようです。このエラーメッセージが表示され続けます:

FetchAPIを読み込めません。プリフライト要求への応答がアクセス制御チェックに合格しません:要求されたリソースに「Access-Control-Allow-Origin」ヘッダーがありません。起源「http://127.0.0.1:3000」がゆえのアクセスが許可されていません。応答のHTTPステータスコードは501でした。不透明な応答がニーズを満たす場合は、リクエストのモードを「no-cors」に設定して、CORSが無効になっているリソースをフェッチします。

これは、ローカルホスト内からそのデータをフェッチしようとしているためであり、ソリューションはCORSを使用する必要があることを理解しています。今、私は実際にそれをしたと思いましたが、どういうわけかそれは私がヘッダーに書いたものを無視するか、問題は何か他のものですか?

それで、実装の問題はありますか?私はそれを間違っていますか?残念ながらサーバーログを確認できません。私は本当にここで少し立ち往生しています。

function performSignIn() {

  let headers = new Headers();

  headers.append('Content-Type', 'application/json');
  headers.append('Accept', 'application/json');

  headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
  headers.append('Access-Control-Allow-Credentials', 'true');

  headers.append('GET', 'POST', 'OPTIONS');

  headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));

  fetch(sign_in, {
      //mode: 'no-cors',
      credentials: 'include',
      method: 'POST',
      headers: headers
    })
    .then(response => response.json())
    .then(json => console.log(json))
    .catch(error => console.log('Authorization failed : ' + error.message));
}

Chromeを使用しています。そのChromeCORSプラグインも使用しようとしましたが、別のエラーメッセージが表示されます。

リクエストの認証情報モードが「include」の場合、応答の「Access-Control-Allow-Origin」ヘッダーの値はワイルドカード「*」であってはなりません。起源「http://127.0.0.1:3000」がゆえのアクセスが許可されていません。XMLHttpRequestによって開始されたリクエストの資格情報モードは、withCredentials属性によって制御されます。

10 answers

1059
sideshowbarker 2017-05-10 13:03.

この回答は多くの分野をカバーしているため、次の3つの部分に分かれています。

  • CORSプロキシを使用して「Access-Control-Allow-Originヘッダーがない」問題を回避する方法
  • CORSプリフライトを回避する方法
  • 「Access-Control-Allow-Originヘッダーはワイルドカードであってはならない」問題を修正する方法

CORSプロキシを使用して「Access-Control-Allow-Originヘッダーがない」問題を回避する方法

フロントエンドJavaScriptコードがリクエストを送信しているサーバーを制御しておらず、そのサーバーからの応答の問題が必要なAccess-Control-Allow-Originヘッダーの不足である場合でも、リクエストを行うことで機能させることができます。 CORSプロキシ。これがどのように機能するかを示すために、最初にCORSプロキシを使用しないコードをいくつか示します。

const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(url)
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))

catchブロックがヒットする理由は、ブラウザがそのコードがから返される応答にアクセスするのを防ぐためhttps://example.comです。そして、ブラウザがそれを行う理由は、Access-Control-Allow-Origin応答に応答ヘッダーがないためです。

これはまったく同じ例ですが、CORSプロキシが追加されています。

const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(proxyurl + url) // https://cors-anywhere.herokuapp.com/https://example.com
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))

注:https://cors-anywhere.herokuapp.comを試したときにダウンしているか利用できない場合は、Herokuに独自のCORS Anywhereサーバーをわずか2〜3分でデプロイする方法について以下を参照してください。

上記の2番目のコードスニペットは、リクエストURLをhttps://cors-anywhere.herokuapp.com/https://example.com;に変更するため、レスポンスに正常にアクセスできます。このようにプロキシURLをプレフィックスとして追加すると、リクエストはそのプロキシを介して行われます。

  1. リクエストをに転送しhttps://example.comます。
  2. からの応答を受け取りhttps://example.comます。
  3. Access-Control-Allow-Origin応答にヘッダーを追加します。
  4. 追加されたヘッダーを使用して、その応答を要求元のフロントエンドコードに返します。

次に、ブラウザはフロントエンドコードが応答にアクセスすることを許可します。これは、Access-Control-Allow-Origin応答ヘッダーを含む応答がブラウザに表示されるためです。

https://github.com/Rob--W/cors-anywhere/のコードを使用して、独自のプロキシを簡単に実行できます
次の5つのコマンドを使用して、独自のプロキシをわずか2〜3分でHerokuに簡単にデプロイすることもできます。

git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master

これらのコマンドを実行すると、たとえば、で実行されている独自のCORSAnywhereサーバーが作成されますhttps://cryptic-headland-94862.herokuapp.com/。したがって、リクエストURLの前に。を付けるのではなく、https://cors-anywhere.herokuapp.com代わりに独自のインスタンスのURLを前に付けますhttps://cryptic-headland-94862.herokuapp.com/https://example.com

したがって、https://cors-anywhere.herokuapp.comを使用しようとしたときに、ダウンしていることがわかった場合(まだダウンしている場合もあります)、Herokuアカウントを取得することを検討してください(まだ取得していない場合)。または、上記の手順を実行して3分で、Herokuに独自のCORSAnywhereサーバーをデプロイします。

独自に実行するか、CORS Anywhereまたは他のオープンプロキシを使用するかに関係なく、このソリューションは、リクエストがブラウザにCORSプリフライトOPTIONSリクエストを実行するようにトリガーするものであっても機能します。その場合、プロキシは必要なヘッダーAccess-Control-Allow-HeadersAccess-Control-Allow-Methodsヘッダーも送り返すためです。プリフライトを成功させます。


CORSプリフライトを回避する方法

問題のコードは、Authorizationヘッダーを送信するため、CORSプリフライトをトリガーします。

https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Preflighted_requests

それがなくてContent-Type: application/jsonも、ヘッダーはプリフライトもトリガーします。

「プリフライト」の意味:ブラウザは、POST質問のコードでを試行する前に、まずOPTIONSサーバーにリクエストを送信します。サーバーが、ヘッダーPOSTを持つクロスオリジンの受信をオプトインしているかどうかを判断します。AuthorizationContent-Type: application/json

小さなcurlスクリプトでかなりうまく機能します-データを取得します。

で適切にテストするcurlにはOPTIONS、ブラウザが送信するプリフライトリクエストをエミュレートする必要があります。

curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \
    -H 'Access-Control-Request-Method: POST' \
    -H 'Access-Control-Request-Headers: Content-Type, Authorization' \
    "https://the.sign_in.url"

https://the.sign_in.url実際のsign_inURLに置き換えられます。

ブラウザがそのOPTIONSリクエストから確認する必要のある応答には、次のようなヘッダーが必要です。

Access-Control-Allow-Origin:  http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization

OPTIONS応答にこれらのヘッダーが含まれていない場合、ブラウザーはそこで停止し、POST要求を送信しようとさえしません。また、応答のHTTPステータスコードは2xx(通常は200または204)である必要があります。それが他のステータスコードの場合、ブラウザはそこで停止します。

問題のサーバーは、OPTIONS501ステータスコードでリクエストに応答していOPTIONSます。これは、リクエストのサポートを実装していないことを示しようとしていることを意味しているようです。この場合、他のサーバーは通常、405「メソッドは許可されていません」ステータスコードで応答します。

したがってPOST、サーバーOPTIONSが405または501、あるいは200または204以外でその要求に応答する場合、または必要なもので応答しない場合、フロントエンドJavaScriptコードからそのサーバーに直接要求を行うことはできません。応答ヘッダー。

問題のケースのプリフライトのトリガーを回避する方法は次のとおりです。

  • サーバーがAuthorizationリクエストヘッダーを必要とせず、代わりに、たとえば、POSTリクエストの本文に埋め込まれた認証データまたはクエリパラメータに依存した場合
  • サーバーがPOST本体にContent-Type: application/jsonメディアタイプを必要とせず、代わりに、値がJSONデータである名前付き(またはその他)のパラメーターとPOST同様に本体を受け入れた場合application/x-www-form-urlencodedjson

「Access-Control-Allow-Originヘッダーはワイルドカードであってはならない」問題を修正する方法

別のエラーメッセージが表示されます:

リクエストの認証情報モードが「include」の場合、応答の「Access-Control-Allow-Origin」ヘッダーの値はワイルドカード「*」であってはなりません。したがって、オリジン 'http://127.0.0.1:3000'はアクセスを許可されていません。XMLHttpRequestによって開始されたリクエストの認証情報モードは、withCredentials属性によって制御されます。

認証情報を含むリクエストの場合、Access-Control-Allow-Originレスポンスヘッダーの値が*。の場合、ブラウザはフロントエンドJavaScriptコードにレスポンスへのアクセスを許可しません。代わりに、その場合の値は、フロントエンドコードのオリジンと完全に一致する必要がありますhttp://127.0.0.1:3000

MDN HTTPアクセス制御(CORS)の記事の「資格情報付きの要求とワイルドカード」を参照してください。

リクエストの送信先のサーバーを制御する場合、このケースに対処する一般的な方法は、Originリクエストヘッダーの値を取得し、Access-Control-Allow-Originそれを応答ヘッダーの値にエコー/反映するようにサーバーを構成することです。例:nginxの場合:

add_header Access-Control-Allow-Origin $http_origin

しかし、それは単なる例です。他の(Web)サーバーシステムは、起点値をエコーする同様の方法を提供します。


Chromeを使用しています。そのChromeCORSプラグインも使ってみました

そのChromeCORSプラグインAccess-Control-Allow-Origin: *は、ブラウザに表示される応答に単純にヘッダーを挿入しているようです。プラグインがよりスマートである場合、プラグインはその偽のAccess-Control-Allow-Origin応答ヘッダーの値をフロントエンドJavaScriptコードの実際のオリジンに設定しますhttp://127.0.0.1:3000

したがって、テストであっても、そのプラグインの使用は避けてください。それはただ気を散らすものです。ブラウザがフィルタリングせずにサーバーから取得する応答をテストするには、curl -H上記のように使用することをお勧めします。


fetch(…)質問のリクエストのフロントエンドJavaScriptコードに関する限り:

headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');

それらの行を削除します。Access-Control-Allow-*ヘッダはレスポンスヘッダ。リクエストでそれらを送信することは決してありません。唯一の効果は、ブラウザをトリガーしてプリフライトを実行することです。

114
Rakesh 2017-10-28 23:17.

このエラーは、ポート番号を含め、クライアントURLとサーバーURLが一致しない場合に発生します。この場合、クロスオリジンリソースシェアリングであるCORSのサービスを有効にする必要があります。

Spring RESTサービスをホストしている場合は、SpringFrameworkのブログ投稿CORSサポートで見つけることができます。

Node.jsサーバーを使用してサービスをホストしている場合は、

  1. Node.jsサーバーを停止します。
  2. npm install cors --save
  3. server.jsに次の行を追加します

    var cors = require('cors')
    
    app.use(cors()) // Use this after the variable declaration
    
63
Lex Soft 2019-01-24 22:30.

この問題は、フロントエンドのリクエストヘッダーとして次のコードを追加したために発生しました。

headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');

これらのヘッダーは、要求ではなく応答に属します。したがって、次の行を含めて、それらを削除します。

headers.append('GET', 'POST', 'OPTIONS');

あなたのリクエストは'Content-Type: application/json'、CORSプリフライトと呼ばれるものをトリガーしました。これにより、ブラウザはOPTIONSメソッドを使用してリクエストを送信しました。詳細については、CORSプリフライトを参照してください。

したがって、バックエンドでは、次のような応答ヘッダーを返すことで、このプリフライトリクエストを処理する必要があります。

Access-Control-Allow-Origin : http://localhost:3000
Access-Control-Allow-Credentials : true
Access-Control-Allow-Methods : GET, POST, OPTIONS
Access-Control-Allow-Headers : Origin, Content-Type, Accept

もちろん、実際の構文は、バックエンドに使用するプログラミング言語によって異なります。

フロントエンドでは、次のようになります。

function performSignIn() {
    let headers = new Headers();

    headers.append('Content-Type', 'application/json');
    headers.append('Accept', 'application/json');
    headers.append('Authorization', 'Basic ' + base64.encode(username + ":" +  password));
    headers.append('Origin','http://localhost:3000');

    fetch(sign_in, {
        mode: 'cors',
        credentials: 'include',
        method: 'POST',
        headers: headers
    })
    .then(response => response.json())
    .then(json => console.log(json))
    .catch(error => console.log('Authorization failed : ' + error.message));
}
10
Harrison O 2019-09-26 11:46.

私の場合、以下のソリューションを使用します

フロントエンドまたはAngular

post(
    this.serverUrl, dataObjToPost,
    {
      headers: new HttpHeaders({
           'Content-Type':  'application/json',
         })
    }
)

バックエンド(私はphpを使用しています)

header("Access-Control-Allow-Origin: http://localhost:4200");
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header("Access-Control-Allow-Headers: Content-Type, Authorization");

$postdata = file_get_contents("php://input");
$request = json_decode($postdata);
print_r($request);
2
hoogw 2018-09-29 09:14.

使用dataType: 'jsonp'は私のために働いた。

   async function get_ajax_data(){
       var _reprojected_lat_lng = await $.ajax({
                                type: 'GET',
                                dataType: 'jsonp',
                                data: {},
                                url: _reprojection_url,
                                error: function (jqXHR, textStatus, errorThrown) {
                                    console.log(jqXHR)
                                },
                                success: function (data) {
                                    console.log(data);

                                    // note: data is already json type, you
                                    //       just specify dataType: jsonp
                                    return data;
                                }
                            });


 } // function               
1
Nalan Madheswaran 2018-07-18 21:30.

これを削除します:

credentials: 'include',
1
Jorge Dominguez 2019-01-14 19:40.

私はSpringRESTを使用していて、AllowedMethodsをWebMvcConfigurerに追加して解決しました。

@Value( "${app.allow.origins}" )
    private String allowOrigins;    
@Bean
public WebMvcConfigurer corsConfigurer() {
            System.out.println("allow origin: "+allowOrigins);
            return new WebMvcConfigurerAdapter() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**")
                    //.allowedOrigins("http://localhost")
                    .allowedOrigins(allowOrigins)
                    .allowedMethods("PUT", "DELETE","GET", "POST");
                }
            };
        }
1
junho 2019-08-30 22:16.

私の場合、Webサーバーは「OPTIONS」メソッドを防止しました

オプションの方法については、Webサーバーを確認してください

「webtier」を使用しています

/www/webtier/domains/[domainname]/config/fmwconfig/components/OHS/VCWeb1/httpd.conf

<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond %{REQUEST_METHOD} ^OPTIONS
  RewriteRule .* . [F]
</IfModule>

への変更

<IfModule mod_rewrite.c>
  RewriteEngine off
  RewriteCond %{REQUEST_METHOD} ^OPTIONS
  RewriteRule .* . [F]
</IfModule>
1
Yair Levy 2019-04-15 22:19.

ちょうど私の2セント... ヘッダーなし」の問題を回避するためにCORSプロキシを使用する方法についてAccess-Control-Allow-Origin

バックエンドでphpを使用している場合、「CORSプロキシ」のデプロイは次のように簡単です。

  1. 次の内容の「no-cors.php」という名前のファイルを作成します。

    $URL = $_GET['url'];
    echo json_encode(file_get_contents($URL));
    die();
    
  2. フロントエンドで、次のような操作を行います。

    fetch('https://example.com/no-cors.php' + '?url=' + url)
      .then(response=>{*/Handle Response/*})`
    
0
Puttamarigowda M S 2020-11-28 00:42.

追加mode:no-corsすると、APIでのcorsの問題を回避できます。

fetch(sign_in, {
        mode: 'no-cors',
        credentials: 'include',
        method: 'POST',
        headers: headers
    })
    .then(response => response.json())
    .then(json => console.log(json))
    .catch(error => console.log('Authorization failed : ' + error.message));
}

Related questions

MORE COOL STUFF

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

スタートレックの50周年を称えるための最良の方法

スタートレックの50周年を称えるための最良の方法

来年は、スペースオペラの最も壮大で野心的なメディアシリーズの50周年を迎えます。しかし、スタートレックはその誇り高い遺産に沿って50歳の誕生日を迎えますか?スタートレックの誕生日を祝う方法はたくさんあります。

更新:合法的な大統領候補は数百万人を怒らせ、美しい女性は苦しむ

更新:合法的な大統領候補は数百万人を怒らせ、美しい女性は苦しむ

(画像提供:ゲッティイメージズ)ドナルド・トランプは、アメリカ合衆国大統領の立候補者となる比類のない外交的洞察力を示し、何百万人もの人々を怒らせ、彼の時代遅れの客体化に対する評価の主要な情報源を失いました。彼が立候補を発表し終える前にパレード。トランプ氏は演説の中で、この国で最も高い役職に選出された場合、米国との南の国境に壁を建設すると述べた一連の声明を発表した。

インターネット上で最も愚かな親ロシアのデマ

インターネット上で最も愚かな親ロシアのデマ

David L. Sternは、ウクライナのキエフを拠点とするフリーランスのライターです。

ディズニーフリークは今、独自の出会い系サイトを持っています

ディズニーフリークは今、独自の出会い系サイトを持っています

オンラインデートに関しては、船長、ベーコン愛好家、ポットヘッド向けに作られたサイトなど、長年にわたって選択できるニッチなサイトがたくさんあります。今、ディズニーファンは彼ら自身のマッチメイキングサイトを通して愛を見つけることができます。

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。

コンセプト ドリフト: AI にとって世界の変化は速すぎる

コンセプト ドリフト: AI にとって世界の変化は速すぎる

私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

犯罪擁護派のオークランドが暴力犯罪者のロミオ・ロレンゾ・パーハムを釈放

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

認知症を患っている 91 歳のアジア人女性が最近、47 番街のアウター サンセット地区でロメオ ロレンゾ パーハムに襲われました。伝えられるところによると、被害者はサンフランシスコの通りを歩いていたところ、容疑者に近づき、攻撃を受け、暴行を受けました。

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

メリック・ガーランドはアメリカに失敗しましたか?

バイデン大統領の任期の半分以上です。メリック・ガーランドは何を待っていますか?

メリック・ガーランドはアメリカに失敗しましたか?

人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。

Language