69

私は、サードパーティのサイトに含まれる JavaScript クライアントを作成しています (Facebook のようなボタンを考えてください)。基本的な HTTP 認証を必要とする API から情報を取得する必要があります。単純化されたセットアップは次のようになります。

サードパーティのサイトには、ページに次のスニペットが含まれています。

<script 
async="true"
id="web-dev-widget"
data-public-key="pUbl1c_ap1k3y"
src="http://web.dev/widget.js">
</script>

widget.jsは API を呼び出します。

var el = document.getElementById('web-dev-widget'),
    user = 'token',
    pass = el.getAttribute('data-public-key'),
    url = 'https://api.dev/',
    httpRequest = new XMLHttpRequest(),
    handler = function() {
      if (httpRequest.readyState === 4) {
        if (httpRequest.status === 200) {
          console.log(httpRequest.responseText);
        } else {
          console.log('There was a problem with the request.', httpRequest);
        }
      }
    };

httpRequest.open('GET', url, true, user, pass);
httpRequest.onreadystatechange = handler;
httpRequest.withCredentials = true;
httpRequest.send();

API は、適切なヘッダーで応答するように構成されています。

Header set Access-Control-Allow-Credentials: true
Header set Access-Control-Allow-Methods: "GET, OPTIONS"
Header set Access-Control-Allow-Headers: "origin, authorization, accept"
SetEnvIf Origin "http(s)?://(.+?\.[a-z]{3})$" AccessControlAllowOrigin=$0
Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin

認証済みの要求 ( ) を送信しているため、ワイルドカードを使用する代わりにAccess-Control-Allow-Originが に設定されていることに注意してください。OriginwithCredentials

これで、非同期のクロスドメイン認証リクエストを作成するための準備が整いました。これは、OS X 10.8.2 の Chrome 25 でうまく機能します。Dev Tools では、リクエストのOPTIONS前にGETリクエストのネットワーク リクエストを確認でき、期待どおりにレスポンスが返ってきます。

Firefox 19 でテストすると、ネットワーク リクエストが Firebug に API に表示されず、次のエラーがコンソールに記録されます。NS_ERROR_DOM_BAD_URI: Access to restricted URI denied

いろいろ調べた結果、コメントによると、Gecko ではユーザー名とパスワードをクロスサイト URI に直接入れることを許可していないことがわかりました。これは、オプションのユーザーとパスワードのパラメーターを使用したことが原因であると想定したopen()ため、資格情報を Base64 でエンコードし、Authorization ヘッダーで送信するという認証済みの要求を作成する別の方法を試しました。

// Base64 from http://www.webtoolkit.info/javascript-base64.html
auth = "Basic " + Base64.encode(user + ":" + pass);

...
// after open() and before send()
httpRequest.setRequestHeader('Authorization', auth);

これにより、Google 検索につながるリクエスト401 Unauthorizedへの応答が返されます。OPTIONSその時、私は自分が困っていることを知りました。

Firefox ではなく Chrome で機能するのなぜですか? OPTIONS要求を一貫して送信および応答するにはどうすればよいですか?

4

3 に答える 3

139

Firefox ではなく Chrome で機能するのなぜですか?

CORS プリフライト リクエストのW3 仕様では、ユーザー資格情報を除外する必要があることが明確に示されています。ChromeWebKitにはOPTIONS、401 のステータスを返すリクエストが引き続き後続のリクエストを送信するというバグがあります。

Firefoxには関連するバグ ファイルがあり、最後にW3 public webapps メーリング リストへのリンクがあり、CORS 仕様を変更してOPTIONS、IIS ユーザーの利益のために要求時に認証ヘッダーを送信できるようにすることを求めています。基本的に、彼らはそれらのサーバーが廃止されるのを待っています。

OPTIONS要求を一貫して送信および応答するにはどうすればよいですか?

OPTIONS認証を必要とせずに、サーバー (この例では API) が要求に応答するようにするだけです。

Kinveyは、ブラウザの問題が報告される数週間前に、興味深いことに、この正確なシナリオのキャッチ 22 問題の概要を示すTwitter API の問題にリンクしながら、これをうまく拡張しました。

于 2013-03-31T20:14:42.697 に答える