1401

どうやら、私はそのセマンティクスを完全に誤解しています。私は次のようなことを考えました:

  1. クライアントは、originhttp://siteAからJavaScript コード MyCode.js をダウンロードします。
  2. MyCode.js の応答ヘッダーにはAccess-Control-Allow-Origin:http://siteBが含まれています。これは、MyCode.js がサイト B へのクロスオリジン参照を許可されていることを意味していると思いました。
  3. クライアントは MyCode.js のいくつかの機能をトリガーしhttp://siteB、クロスオリジン リクエストであるにもかかわらず、これは にリクエストを送信します。

まあ、私は間違っています。このようにまったく機能しません。だから、私はCross-Origin Resource Sharingを読み、 w3cの推奨事項で Cross-Origin Resource Sharing を読み込もうとしました

1 つ確かなことは、このヘッダーをどのように使用すればよいのか、まだ理解できていないということです。

サイト A とサイト B の両方を完全に制御できます。サイト A からダウンロードした JavaScript コードが、このヘッダーを使用してサイト B のリソースにアクセスできるようにするにはどうすればよいですか?

PS

JSONP を利用したくありません。

4

18 に答える 18

1704

Access-Control-Allow-OriginCORS (Cross-Origin Resource Sharing) ヘッダーです。

サイト A がサイト B からコンテンツをフェッチしようとすると、サイト B はAccess-Control-Allow-Origin応答ヘッダーを送信して、このページのコンテンツが特定のオリジンにアクセス可能であることをブラウザーに伝えることができます。( originドメインにスキームとポート番号を加えたものです。) デフォルトでは、サイト B のページは他の origin からはアクセスできません。ヘッダーを使用するとAccess-Control-Allow-Origin、特定の要求オリジンによるクロスオリジン アクセスのドアが開きます。

サイト B がサイト A にアクセスできるようにしたいリソース/ページごとに、サイト B はそのページに応答ヘッダーを付けて提供する必要があります。

Access-Control-Allow-Origin: http://siteA.com

最新のブラウザは、クロスドメイン リクエストを完全にブロックしません。サイト A がサイト B からページをリクエストすると、ブラウザは実際にリクエストされたページをネットワーク レベルで取得し、応答ヘッダーにサイト A が許可されたリクエスタ ドメインとしてリストされているかどうかを確認します。サイト A がこのページへのアクセスを許可されていることをサイト B が示していない場合、ブラウザはXMLHttpRequesterrorイベントをトリガーし、要求元の JavaScript コードへの応答データを拒否します。

単純でない要求

ネットワーク レベルで発生することは、上記の説明よりも少し複雑になる可能性があります。リクエストが「単純でない」リクエストの場合、ブラウザは最初にデータのない「プリフライト」OPTIONS リクエストを送信して、サーバーがリクエストを受け入れるかどうかを確認します。次のいずれか (または両方) の場合、リクエストは単純ではありません。

  • GET または POST 以外の HTTP 動詞の使用 (PUT、DELETE など)
  • 単純でないリクエスト ヘッダーを使用する。単純なリクエスト ヘッダーは次のとおりです。
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Typeapplication/x-www-form-urlencoded(これは、値が、multipart/form-data、またはの場合にのみ単純ですtext/plain)

サーバーが、単純でない動詞や単純でないヘッダーに一致する適切な応答ヘッダー (Access-Control-Allow-Headers単純でないヘッダー、単純でない動詞の場合) を使用して OPTIONS プリフライトに応答する場合、ブラウザーは実際の要求を送信します。Access-Control-Allow-Methods

サイト A が の PUT リクエストを送信したいと仮定すると/somePage、ブラウザは最初にプリフライト リクエストを送信しますContent-Typeapplication/json

OPTIONS /somePage HTTP/1.1
Origin: http://siteA.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

Access-Control-Request-MethodAccess-Control-Request-Headersはブラウザによって自動的に追加されることに注意してください。それらを追加する必要はありません。この OPTIONS プリフライトは、成功した応答ヘッダーを取得します。

Access-Control-Allow-Origin: http://siteA.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type

実際のリクエストを送信するとき (プリフライトが完了した後)、動作は単純なリクエストの処理方法と同じです。つまり、プリフライトが成功した非単純なリクエストは、単純なリクエストと同じように扱われます (つまり、サーバーAccess-Control-Allow-Originは実際の応答のために再度送信する必要があります)。

ブラウザーは実際の要求を送信します。

PUT /somePage HTTP/1.1
Origin: http://siteA.com
Content-Type: application/json

{ "myRequestContent": "JSON is so great" }

サーバーAccess-Control-Allow-Originは単純なリクエストの場合と同じように、を返します。

Access-Control-Allow-Origin: http://siteA.com

非単純なリクエストの詳細については、CORS を介した XMLHttpRequest の理解を参照してください。

于 2012-05-17T13:33:26.440 に答える
140

Cross-Origin Resource Sharing - CORS(AKA Cross-Domain AJAX request) は、ほとんどの Web 開発者が遭遇する可能性のある問題です。Same-Origin-Policy によると、ブラウザはセキュリティ サンドボックスでクライアント JavaScript を制限します。通常、JS はリモート サーバーと直接通信できません。別のドメインから。これまで開発者は、クロスドメイン リソース リクエストを実現するための多くのトリッキーな方法を作成してきましたが、最も一般的に使用される方法は次のとおりです。

  1. Flash/Silverlight またはサーバー側を「プロキシ」として使用して、リモートと通信します。
  2. パディング付き JSON ( JSONP )。
  3. リモート サーバーを iframe に埋め込み、fragment または window.name を介して通信します。こちらを参照してください。

これらのトリッキーな方法には多かれ少なかれいくつかの問題があります。たとえば、JSONP は開発者が単純に「評価」するとセキュリティ ホールが発生する可能性があり、上記の #3 は機能しますが、両方のドメインが相互に厳密な契約を構築する必要があり、柔軟性もエレガントさもありません。私見では:)

W3C は、この問題を解決するための安全で柔軟な、推奨される標準的な方法を提供する標準ソリューションとして、クロスオリジン リソース共有 (CORS) を導入しました。

メカニズム

高レベルから、CORS はドメイン A からのクライアント AJAX 呼び出しとドメイン B でホストされているページとの間のコントラクトであると単純に見なすことができます。典型的なクロスオリジン リクエスト/レスポンスは次のようになります。

DomainA AJAX 要求ヘッダー

Host DomainB.com
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json
Accept-Language en-us;
Accept-Encoding gzip, deflate
Keep-Alive 115
Origin http://DomainA.com 

DomainB 応答ヘッダー

Cache-Control private
Content-Type application/json; charset=utf-8
Access-Control-Allow-Origin DomainA.com
Content-Length 87
Proxy-Connection Keep-Alive
Connection Keep-Alive

上でマークした青い部分はカーネルの事実であり、「オリジン」リクエストヘッダーは「クロスオリジンリクエストまたはプリフライトリクエストの発信元を示します」、「アクセス制御-許可-オリジン」レスポンスヘッダーは、このページがリモートリクエストを許可していることを示していますDomainA (値が * の場合は、任意のドメインからのリモート要求を許可することを示します)。

上で述べたように、W3 は、実際に Cross-Origin HTTP リクエストを送信する前に「プリフライト リクエストOPTIONS」を実装するブラウザを推奨しました。一言で言えば、これは HTTPリクエストです。

OPTIONS DomainB.com/foo.aspx HTTP/1.1

foo.aspx が OPTIONS HTTP 動詞をサポートしている場合、次のような応答が返されることがあります。

HTTP/1.1 200 OK
Date: Wed, 01 Mar 2011 15:38:19 GMT
Access-Control-Allow-Origin: http://DomainA.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, HEAD
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Max-Age: 1728000
Connection: Keep-Alive
Content-Type: application/json

応答に「Access-Control-Allow-Origin」が含まれ、その値が「*」であるか、CORS 要求を送信したドメインが含まれている場合にのみ、この必須条件を満たすことで、ブラウザは実際のクロスドメイン要求を送信し、結果をキャッシュします「Preflight-Result-Cache」内。

私は 3 年前に CORS についてブログを書きました: AJAX Cross-Origin HTTP request

于 2014-01-23T13:54:54.860 に答える
4

クロス オリジン共有の場合は、ヘッダーを設定します。'Access-Control-Allow-Origin':'*';

Php:header('Access-Control-Allow-Origin':'*');

ノード:app.use('Access-Control-Allow-Origin':'*');

これにより、異なるドメインのコンテンツを共有できます。

于 2016-11-28T02:39:37.513 に答える
2

Nginxとアパッチ

apsillersの回答に加えて、リクエストが単純かどうかを示すwikiグラフを追加したいと思います(およびOPTIONSプリフライトリクエストが送信されるかどうか)

ここに画像の説明を入力してください

単純なリクエスト (イメージのホットリンクなど) の場合、サーバー構成ファイルを変更する必要はありませんが、Melvin Guerrero の回答で言及されているように、アプリケーション (サーバー上でホストされている、php など) にヘッダーを追加できますが、覚えておいてください: 完全に追加する場合サーバー(config)のcorsヘッダーと同時に、アプリケーション(phpなど)で単純なcorsを許可すると、まったく機能しません。

そして、ここに2つの一般的なサーバーの構成があります

  • Nginx で CORS をオンにする(nginx.confファイル)

    location ~ ^/index\.php(/|$) {
       ...
        add_header 'Access-Control-Allow-Origin' "$http_origin" always; # if you change "$http_origin" to "*" you shoud get same result - allow all domain to CORS (but better change it to your particular domain)
        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';  # arbitrary methods
            add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin'; # arbitrary headers
            add_header 'Content-Length' 0;
            add_header 'Content-Type' 'text/plain charset=UTF-8';
            return 204;
        }
    }

  • Apache でCORS をオンにする(ファイル.htaccess)

    # ------------------------------------------------------------------------------
    # | Cross-domain Ajax requests                                                 |
    # ------------------------------------------------------------------------------
    
    # Enable cross-origin Ajax requests.
    # http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
    # http://enable-cors.org/
    
    # change * (allow any domain) below to your domain
    Header set Access-Control-Allow-Origin "*"
    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"
    Header always set Access-Control-Allow-Credentials "true"

于 2020-05-15T09:33:09.143 に答える
1

Access-Control-Allow-Origin 応答ヘッダーは、指定されたオリジンからの要求コードと応答を共有できるかどうかを示します。

Header type Response       header
Forbidden header name      no

任意のオリジンからのコードがリソースにアクセスできるようにブラウザに指示する応答には、次のものが含まれます。

Access-Control-Allow-Origin: *

詳細については、こちらをご覧ください....

于 2019-01-31T11:49:26.977 に答える