web-dev-qa-db-ja.com

認証されたCORSリクエストのプリフライトOPTIONSリクエストがChromeで機能するのに、Firefoxでは機能しないのはなぜですか?

私はサードパーティのサイトに含まれるJavaScriptクライアントを書いています(Facebook Likeボタンを考えてください)。基本的な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

資格情報のリクエスト(Origin)を送信しているため、ワイルドカードを使用する代わりにAccess-Control-Allow-OriginwithCredentialsに設定されていることに注意してください。

非同期のクロスドメイン認証リクエストを作成するためのすべての準備が整い、OS X 10.8.2のChrome 25でうまく機能します。開発ツールでは、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);

これにより、OPTIONSリクエストに対する401 Unauthorizedレスポンスが発生し、「FirefoxではなくChromeで機能する理由」などのGoogle検索につながります。それは私が困っていることを知ったときです。

FirefoxではなくChromeで動作するのはなぜですか?一貫して送信および応答するOPTIONSリクエストを取得するにはどうすればよいですか?

58
maxbeatty

なぜdoesFirefoxではなくChromeで動作するのですか?

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

Firefox へのリンクで終わる関連バグが報告されています W3 public webapps mailing list 認証ヘッダーをOPTIONSで送信できるようにCORS仕様を変更するように要求IISユーザーの利益のためにリクエストします。基本的に、これらのサーバーが廃止されるのを待っています。

一貫して送信および応答するOPTIONSリクエストを取得するにはどうすればよいですか?

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

Kinvey これを拡張しながら、 Twitter APIの問題 このシナリオのキャッチ22問題の概要を、興味深いことに、ブラウザの問題が提出されました。

118
maxbeatty

これは古い投稿ですが、おそらくこれは人々がCORS問題を完了するのを助けるかもしれません。基本的な認証の問題を完了するには、サーバーでOPTIONSリクエストの認証を回避する必要があります。これはApacheの構成例です。 VirtualHostまたはLocationにこのようなものを追加するだけです。

<LimitExcept OPTIONS>
    AuthType Basic
    AuthName <AUTH_NAME>
    Require valid-user
    AuthUserFile <FILE_PATH>
</LimitExcept>
2

それは私にとって特別でした。 「SESSIONHASH」という名前のヘッダーを送信しています。 ChromeとOperaには問題ありませんが、Firefoxは「Access-Control-Allow-Headers」リストにこのヘッダーが必要です。そうしないと、FirefoxはCORSエラーをスローします。

0
bitkorn