web-dev-qa-db-ja.com

jQuery AJAX呼び出しはエラーステータス403になります

JQuery AJAXを使用して、Webサービスへのクエリを作成しています。私のクエリは次のようになります。

var serviceEndpoint = 'http://example.com/object/details?version=1.1';
$.ajax({
  type: 'GET', 
  url: serviceEndpoint,
  dataType: 'jsonp',
  contentType: 'jsonp',
  headers: { 'api-key':'myKey' },
  success: onSuccess,
  error: onFailure
});

これを実行すると、403のステータスエラーが発生します。呼び出しの結果がステータスコード403になる理由がわかりません。サービスのセキュリティを管理しており、ワイドオープンとしてマークされています。キーが有効であることはわかっています。これは別の呼び出しで使用しているためです。動作する呼び出しは次のとおりです。

var endpoint = 'http://example.com/object/data/item?version=1.1';
$.ajax({ 
  type: 'POST', 
  url: endpoint, 
  cache: 'false',
  contentType:'application/json',
  headers: {
    'api-key':'myKey',
    'Content-Type':'application/json'
  },
  data: JSON.stringify({
    id: 5,
    count:true
  }),
  success: onDataSuccess,
  error: onDataFailure
});

これらは2つの異なるエンドポイントであることを知っています。しかし、これはサーバー側の認証エラーでも許可エラーでもないと確信しています。繰り返しになりますが、サーバー側ではすべてが開かれています。これは、クライアント側のリクエストで間違いを犯していることを意味します。

開発中にこのリクエストが行われていることを伝える必要があります。したがって、私はこれを http:// localhost:30 から実行しています。そのため、すぐにそれがCORSの問題であると思いました。しかし、すべてが正しいように見えます。私のPOSTリクエストは機能しますが、私のGETにはまったくイライラしません。何かが足りませんか?

12
Some User

403エラーの理由は、ヘッダーを送信していないことです。 CORSリクエストを行っているため、サーバーが応答にAccess-Control-Allow-Headersを追加してこれらのヘッダーを有効にしない限り、カスタムヘッダーを送信できません。

preflighted-request の場合、クライアントはサーバーに対して2つの要求を行います。 1つ目はプリフライト(OPTIONSメソッドを使用)で、2つ目は実際のリクエストです。サーバーは、プリフライト要求の応答として Access-Control-Allow-Headers ヘッダーを送信します。そのため、いくつかのヘッダーを送信できます。この方法により、POSTリクエストはプリフライトリクエストであるため、POSTリクエストは機能します。ただし、GETリクエストの場合、収集するプリフライトはありません。 Access-Control-Allow-Headers header。この場合、ブラウザはカスタムヘッダーを送信しません。

この問題の回避策:

回避策として、次のようにdataTypeおよびcontentTypejsonに設定します。

var serviceEndpoint = 'http://example.com/object/details?version=1.1';
$.ajax({
  type: 'GET', 
  url: serviceEndpoint,
  dataType: 'json',
  contentType: 'json',
  headers: { 'api-key':'myKey' },
  success: onSuccess,
  error: onFailure
});

この方法では、getリクエストはpreflighted requestになります。サーバーで Access-Control-Allow-Headers ヘッダーを使用してapi-keyを有効にすると、機能します。

上記のリクエストのサーバー構成のサンプル(express.jsで記述):

res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', '*');
res.setHeader('Access-Control-Allow-Headers', 'api-key,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);

追加:

実際には、contentTypeはjsonpリクエストの実行中にapplication/javascriptまたはapplication/jsonのいずれかになります。 contentTypeとしてjsonpはありません。

20
ykaragol

JQueryのAjax呼び出しの APIページ を見ると、Content-Typeセクションで次のことが言及されています。

注:クロスドメインリクエストの場合、コンテンツタイプをapplication/x-www-form-urlencoded、multipart/form-data以外に設定し、または、text/plainがブラウザをトリガーして、プリフライトOPTIONSリクエストをサーバーに送信します。

そのページでは、「プリフライトOPTIONSリクエスト」とは実際には言及していませんが、そのフレーズをオンラインで調べると、興味深いリンクが見つかりました。

興味深いのは、HTML5Rocksページの コード例CORS画像 です。この画像は、JavaScriptコードからブラウザー、サーバー、サーバーへのAjax呼び出しがどのように行われるか、およびこれら3つすべての間で応答が往復する様子を示しています。

私たちはJavaScript + Browser = Clientを考える傾向がありますが、イラストでは著者がWeb開発者のコ​​ードとブラウザ開発者のコ​​ードの違いを説明しています。前者はJavaScriptコードで書かれていますが、後者はC、C++を使用して書かれていますまたはC#コード。

優れたパケットアナライザーツールは Fiddler で、これは Wireshark に似ています。これらのツールのいずれかは、ブラウザからサーバーに送信されているプリフライトリクエストを表示する必要があります。最も可能性が高いのは、Ajaxリクエストが 403 Forbidden error でサーバーによってブロックされている場所です。

0
Clomp