Postmanが受け取らないのに、JavaScriptコードが「要求されたリソースに 'Access-Control-Allow-Origin'ヘッダーがありません」というエラーを受け取るのはなぜですか?

2013年11月18日に質問されました。  ·  閲覧回数 4.5M回  ·  ソース

Mr Jedi picture
2013年11月18日

Modノート:この質問は、PostmanがXMLHttpRequestと同じようにCORS制限の対象にならない理由についてです。 この質問は、「いいえ『アクセス制御-許可-起源』 ...」エラーを修正する方法に関するもの

投稿を停止してください


RESTful APIの組み込みFlaskに接続して、 JavaScriptを使用して認証を行おうとしています。 ただし、リクエストを行うと、次のエラーが発生します。

XMLHttpRequestはhttp:// myApiUrl / loginをロードできません。 要求されたリソースに「Access-Control-Allow-Origin」ヘッダーがありません。 したがって、オリジン 'null'はアクセスを許可されません。

APIまたはリモートリソースがヘッダーを設定する必要があることは知っていますが、Chrome拡張機能Postmanを介してリクエストを行ったときになぜそれが機能したのですか?

これはリクエストコードです:

$.ajax({
    type: "POST",
    dataType: 'text',
    url: api,
    username: 'user',
    password: 'pass',
    crossDomain : true,
    xhrFields: {
        withCredentials: true
    }
})
    .done(function( data ) {
        console.log("done");
    })
    .fail( function(xhr, textStatus, errorThrown) {
        alert(xhr.responseText);
        alert(textStatus);
    });

回答

MD. Sahib Bin Mahboob picture
2013年11月18日
1404

私がそれを正しく理解していれば、あなたはあなたのページが置かれているのとは異なるドメインに対してXMLHttpRequestを実行しています。 そのため、セキュリティ上の理由から、通常は同じオリジンでのリクエストが許可されるため、ブラウザはそれをブロックしています。 クロスドメインリクエストを実行する場合は、別のことを行う必要があります。 これを実現する方法についてのチュートリアルは、 CORSの使用です。

postmanを使用している場合、このポリシーによる制限はありません。 Cross-Origin XMLHttpRequestからの引用:

通常のWebページはXMLHttpRequestオブジェクトを使用してリモートサーバーとデータを送受信できますが、同一生成元ポリシーによって制限されます。 拡張機能はそれほど制限されていません。 拡張機能は、最初にクロスオリジン権限を要求する限り、オリジン外のリモートサーバーと通信できます。

Shady Mohamed Sherif picture
2014年12月04日
266

警告: Access-Control-Allow-Origin: *使用すると、API / Webサイトがクロスサイトリクエストフォージェリ(CSRF)攻撃に対して脆弱になる可能性があります。 このコードを使用する前に理解していることを確認してください。

PHPを使用している場合、解決するのは非常に簡単です。 リクエストを処理するPHPページの先頭に次のスクリプトを追加するだけです。

<?php header('Access-Control-Allow-Origin: *'); ?>

Node-redを使用している場合は、次の行のコメントを解除して、 node-red/settings.jsファイルでCORSを許可する必要があります。

// The following property can be used to configure cross-origin resource sharing
// in the HTTP nodes.
// See https://github.com/troygoode/node-cors#configuration-options for
// details on its contents. The following is a basic permissive set of options:
httpNodeCors: {
 origin: "*",
 methods: "GET,PUT,POST,DELETE"
},

質問と同じようにFlaskを使用している場合。 最初にflask-corsをインストールする必要があります

$ pip install -U flask-cors

次に、Flaskcorsをアプリケーションに含めます。

from flask_cors import CORS

単純なアプリケーションは次のようになります。

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

詳細については、 Flaskのドキュメントを確認してください。

George Livingston picture
2016年12月13日
68

なぜなら
$ .ajax({type: "POST" -OPTIONSを呼び出します
($ .post - POSTを呼び出します。

どちらも違います。 郵便配達員はきちんと「POST」と呼んでいますが、呼んでみると「OPTIONS」になります。

C#Webサービスの場合-Web API

次のコードをweb.configファイルの<system.webServer>タグの下に追加してください。 これは機能します:

<httpProtocol>
    <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
    </customHeaders>
</httpProtocol>

Ajax通話で間違いをしていないことを確認してください

jQuery

$.ajax({
    url: 'http://mysite.microsoft.sample.xyz.com/api/mycall',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    type: "POST", /* or type:"GET" or type:"PUT" */
    dataType: "json",
    data: {
    },
    success: function (result) {
        console.log(result);
    },
    error: function () {
        console.log("error");
    }
});

注:サードパーティのWebサイトからコンテンツをダウンロードする場合、これは役に立ちません。 次のコードを試すことはできますが、JavaScriptを試すことはできません。

System.Net.WebClient wc = new System.Net.WebClient();
string str = wc.DownloadString("http://mysite.microsoft.sample.xyz.com/api/mycall");
Kamil Kiełczewski picture
2019年12月16日
17

以下のAPIとしての調査では、最初の質問が機能しているため、質問のhttp:// myApiUrl / loginの代わりにhttp://example.comを使用します。

あなたのページはhttp://my-site.local:8088にあると思います

異なる結果が表示される理由は、Postman:

  • ヘッダーを設定Host=example.com (API)
  • ヘッダーを設定しないOrigin

これは、サイトとAPIが同じドメインを持っている場合のブラウザーのリクエスト送信方法に似ています(ブラウザーはヘッダー項目Referer=http://my-site.local:8088も設定しますが、Postmanには表示されません)。 Originヘッダーが設定されていない場合、通常、サーバーはデフォルトでそのような要求を許可します。

Enter image description here

これは、Postmanがリクエストを送信する標準的な方法です。 ただし、サイトとAPIのドメインが異なる場合、ブラウザは異なるCORSが発生し、ブラウザは自動的に次のようになります。

  • ヘッダーを設定しますHost=example.com (APIとしてあなたのもの)
  • ヘッダーを設定しますOrigin=http://my-site.local:8088 (あなたのサイト)

(ヘッダーReferer値はOriginと同じです)。 そして今、Chromeの[コンソールとネットワーク]タブに次のように表示されます。

Enter image description here

Enter image description here

Host != Originがある場合、これはCORSであり、サーバーがそのようなリクエストを検出すると、通常、デフォルトでブロックされます

Origin=nullは、ローカルディレクトリからHTMLコンテンツを開くときに設定され、リクエストを送信します。 同じ状況は、以下のスニペットのように、 <iframe>内でリクエストを送信する場合です(ただし、ここではHostヘッダーはまったく設定されていません)-一般に、HTML仕様で不透明と記載されているすべての場所で起源、あなたはそれをOrigin=null翻訳することができます。 これについての詳細はここで見つけることができ

fetch('http://example.com/api', {method: 'POST'});
Look on chrome-console > network tab

単純なCORSリクエストを使用しない場合、通常、ブラウザはメインリクエストを送信する前にOPTIONSリクエストも自動的に送信します。詳細については

fetch('http://example.com/api', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json'}
});
Look in chrome-console -> network tab to 'api' request.
This is the OPTIONS request (the server does not allow sending a POST request)

サーバーの構成を変更して、CORSリクエストを許可することができます。

これは、 nginx (nginx.confファイル)でalways/"$http_origin" "*" 、Apacheにalways/"$http_origin"十分に注意してください。これにより、任意のドメインからCORSのブロックが解除されます。

location ~ ^/index\.php(/|$) {
   ...
    add_header 'Access-Control-Allow-Origin' "$http_origin" always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    if ($request_method = OPTIONS) {
        add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        return 204;
    }
}

Apache

# ------------------------------------------------------------------------------
# | Cross-domain Ajax requests                                                 |
# ------------------------------------------------------------------------------

# Enable cross-origin Ajax requests.
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# http://enable-cors.org/

# <IfModule mod_headers.c>
#    Header set Access-Control-Allow-Origin "*"
# </IfModule>

# Header set Header set Access-Control-Allow-Origin "*"
# Header always set Access-Control-Allow-Credentials "true"

Access-Control-Allow-Origin "http://your-page.com:80"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Allow-Headers "My-First-Header,My-Second-Header,Authorization, content-type, csrf-token"
Gopinath picture
2020年02月02日
12

CORS制限の適用は、サーバーによって定義され、ブラウザーによって実装されるセキュリティ機能

ブラウザはサーバーのCORSポリシーを確認し、それを尊重します。

ただし、PostmanツールはサーバーのCORSポリシーを気にしません。

そのため、CORSエラーはブラウザに表示されますが、Postmanには表示されません。

Kms picture
2020年03月11日
8

異なるユースケースで同じエラーが発生しました。

ユースケース: SpringRESTエンドポイントを角度で呼び出そうとしたときのクロム。

enter image description here

解決策:それぞれのコントローラークラスの上に@CrossOrigin( "*")アノテーションを追加します。

enter image description here

Adwaith picture
2020年07月22日
3

javascriptでfetchAPIまたはXMLHttpRequestを使用してコンテンツをフェッチするときにこの制限を回避する場合は、プロキシサーバーを使用して、ヘッダーAccess-Control-Allow-Origin*ます。

const express = require('express');
const request = require('request');

const app = express();

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  next();
});

app.get('/fetch', (req, res) => {
  request(
    { url: req.query.url },
    (error, response, body) => {
      if (error || response.statusCode !== 200) {
        return res.status(500).send('error');
      }
      res.send(body);
    }
  )
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));

上記は、プロキシサーバーとして機能できるサンプルコード(ノードJが必要)です。 例:通常https://www.google.comをフェッチしたい場合、CORSエラーがスローされますが、リクエストはポート3000でローカルにホストされているプロキシサーバーを介して送信されるため、プロキシサーバーはAccess-Control-Allow-Originヘッダーを追加します応答で、問題はありません。

フェッチするURlにリクエストを直接送信する代わりに、GETリクエストをhttp:// localhost:3000 / fetch?url = Your URL hereに送信します。

Your URL hereは、取得するURLを表します。例: https://www.google.com

Shakti Srivastav picture
2020年04月19日
0

.NET Core Web APIプロジェクトの場合のみ、次の変更を追加します。

  1. Startup.csファイルのConfigureServices()メソッドのservices.AddMvc()行の後に次のコードを追加します。
services.AddCors(allowsites=>{allowsites.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin());
            });
  1. Startup.csファイルのConfigure()メソッドのapp.UseMvc()行の後に次のコードを追加します。
app.UseCors(options => options.AllowAnyOrigin());
  1. ドメイン外でアクセスするコントローラーを開き、コントローラーレベルで次の属性を追加します。
[EnableCors("AllowOrigin")]
Sai Vaibhav Medavarapu picture
2020年03月10日
-1

中間層として.NETを使用する場合は、たとえば、ルート属性を明確に確認してください。

こんな時に問題があったけど、

[Route("something/{somethingLong: long}")] //Space.

これで修正しました、

[Route("something/{somethingLong:long}")] //No space