私はサードパーティのサイトに含まれる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-Origin
がwithCredentials
に設定されていることに注意してください。
非同期のクロスドメイン認証リクエストを作成するためのすべての準備が整い、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
リクエストを取得するにはどうすればよいですか?
なぜdoesFirefoxではなくChromeで動作するのですか?
CORSプリフライトリクエストのW3仕様 は、ユーザー資格情報を除外する必要があることを明確に示しています。 Chrome と WebKit にはバグがあり、401のステータスを返すOPTIONS
要求は引き続き後続の要求を送信します。
Firefox へのリンクで終わる関連バグが報告されています W3 public webapps mailing list 認証ヘッダーをOPTIONS
で送信できるようにCORS仕様を変更するように要求IISユーザーの利益のためにリクエストします。基本的に、これらのサーバーが廃止されるのを待っています。
一貫して送信および応答するOPTIONS
リクエストを取得するにはどうすればよいですか?
サーバー(この例ではAPI)に、認証を要求せずにOPTIONS
要求に応答させるだけです。
Kinvey これを拡張しながら、 Twitter APIの問題 このシナリオのキャッチ22問題の概要を、興味深いことに、ブラウザの問題が提出されました。
これは古い投稿ですが、おそらくこれは人々がCORS問題を完了するのを助けるかもしれません。基本的な認証の問題を完了するには、サーバーでOPTIONSリクエストの認証を回避する必要があります。これはApacheの構成例です。 VirtualHostまたはLocationにこのようなものを追加するだけです。
<LimitExcept OPTIONS>
AuthType Basic
AuthName <AUTH_NAME>
Require valid-user
AuthUserFile <FILE_PATH>
</LimitExcept>
それは私にとって特別でした。 「SESSIONHASH」という名前のヘッダーを送信しています。 ChromeとOperaには問題ありませんが、Firefoxは「Access-Control-Allow-Headers」リストにこのヘッダーが必要です。そうしないと、FirefoxはCORSエラーをスローします。