OPTIONSプリフライトリクエストをスキップするにはどうすればよいですか?


92

PhoneGapアプリを開発しましたが、今はモバイルウェブサイトに変わります。1つの小さな不具合以外はすべてスムーズに機能します。POSTリクエストを介して特定のサードパーティAPIを使用していますが、これはアプリでは問題なく機能しますが、モバイルWebサイトバージョンでは失敗します。

よく見ると、AngularJS(私はブラウザを推測します)が最初にOPTIONSリクエストを送信しているようです。今日、CORSについて多くのことを学びましたが、CORSを完全に無効にする方法がわかりません。私はそのAPIにアクセスできません(そのため、その側での変更は不可能です)が、私が取り組んでいるドメインをAccess-Control-Allow-Originヘッダーに追加しました。

これは私が話しているコードです:

        var request = {
                language: 'fr',
                barcodes: [
                    {
                        barcode: 'somebarcode',
                        description: 'Description goes here'
                    }
                ]
            };
        }
        var config = {
            headers: { 
                'Cache-Control': 'no-cache',
                'Content-Type': 'application/json'
            }
        };
        $http.post('http://somedomain.be/trackinginfo', request, config).success(function(data, status) {
            callback(undefined, data);
        }).error(function(data, status) {
            var err = new Error('Error message');
            err.status = status;
            callback(err);
        });

ブラウザー(またはAngularJS)がそのOPTIONSリクエストを送信しないようにして、実際のP​​OSTリクエストにスキップする方法を教えてください。AngularJS 1.2.0を使用しています。

前もって感謝します。

回答:


100

プリフライトは、Content-Typeがトリガーされていますapplication/json。これを防止する最も簡単な方法は、Content-Typeをtext/plainあなたのケースに設定することです。application/x-www-form-urlencodedmultipart/form-dataContent-Typesも使用できますが、もちろんリクエストペイロードを適切にフォーマットする必要があります。

この変更を行ってもまだプリフライトが表示される場合は、AngularがリクエストにXヘッダーも追加している可能性があります。

または、それをトリガーするヘッダー(Authorization、Cache-Control ...)があるかもしれません。以下を参照してください:


9
これが正解です。Content-TypeヘッダーとCache-Controlヘッダーがプリフライトリクエストをトリガーしています。Content-Typeがtext / plainのプレーンなGETと他のいくつかは、プリフライトされていないリクエストをトリガーする唯一の方法です。参照:developer.mozilla.org/en-US/docs/HTTP/...
ジェフ・ハバード

ああ、そうです、Cache-Controlを忘れてしまいました。
レイニコラス2014

15
カスタムヘッダーもプリフライトをトリガーします。
セバスチャン・デプレ

1
OPTIONsテストを防ぐためにコンテンツタイプを変更することは、答えではありません。コンテンツタイプは、コンテンツタイプに関係なく一致する必要があります
ekerner

ブラウザがスローしていて、バックエンドでHttpメソッドOPTIONSがブロックされている場合、OPTIONSが失敗したため、ブラウザがPOST / PUTの対応するAPIを呼び出さないような効果がありますか?
Pサティシュパトロ

16

レイが言ったように、コンテンツヘッダーを次のように変更することでそれを止めることができます-

 $http.defaults.headers.post["Content-Type"] = "text/plain";

例えば ​​-

angular.module('myApp').factory('User', ['$resource','$http',
    function($resource,$http){
        $http.defaults.headers.post["Content-Type"] = "text/plain";
        return $resource(API_ENGINE_URL+'user/:userId', {}, {
            query: {method:'GET', params:{userId:'users'}, isArray:true},
            getLoggedIn:{method:'GET'}
        });
    }]);

または直接電話する-

var req = {
 method: 'POST',
 url: 'http://example.com',
 headers: {
   'Content-Type': 'text/plain'
 },
 data: { test: 'test' }
}

$http(req).then(function(){...}, function(){...});

これは飛行前のオプション要求を送信しません。

注:リクエストにはカスタムヘッダーパラメータを含めないでください。リクエストヘッダーにカスタムヘッダーが含まれている場合、ブラウザはプリフライトリクエストを作成するため、これを回避することはできません。


1
どうすればいい$httpですか?
学習者2016年

ありがとう、それは私がやっていたことに似ています。唯一の変更点は、メソッドGETと追加のヘッダーAuthorizationです。しかし、まだプリフライトを送信しています。
学習者2016年

1
ここにリクエストを貼り付けられますか?カールか何か?Authorizationヘッダーが原因である可能性があります。それを削除してから、もう一度試してください。カスタムヘッダーを送信する場合、angularはプリフライトリクエストを送信します。
vivex 2016年

pastebin.com/vRDeFiH2 1つ目は$ httpへのリクエストで、2つ目は有効なリクエストで、postmanによってビルドされます:)
learnercys

2

特定のタイプのクロスドメインAJAXリクエストを実行する場合、CORSをサポートする最新のブラウザーは追加の「プリフライト」リクエストを挿入して、アクションを実行する権限があるかどうかを判断します。クエリ例から:

$http.get( https://example.com/api/v1/users/’ +userId,
  {params:{
           apiKey:’34d1e55e4b02e56a67b0b66
          }
  } 
);

このフラグメントの結果として、アドレスに2つの要求(OPTIONSとGET)が送信されたことがわかります。サーバーからの応答には、クエリGETの許容性を確認するヘッダーが含まれます。サーバーがOPTIONS要求を正しく処理するように構成されていない場合、クライアント要求は失敗します。例えば:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: accept, origin, x-requested-with, content-type
Access-Control-Allow-Methods: DELETE
Access-Control-Allow-Methods: OPTIONS
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Methods: GET
Access-Control-Allow-Methods: POST
Access-Control-Allow-Orgin: *
Access-Control-Max-Age: 172800
Allow: PUT
Allow: OPTIONS
Allow: POST
Allow: DELETE
Allow: GET

2

最善の方法は、リクエストのタイプが「OPTIONS」であるかどうかをチェックし、ミドルウェアから200を返すことだと思います。それは私のために働いた。

express.use('*',(req,res,next) =>{
      if (req.method == "OPTIONS") {
        res.status(200);
        res.send();
      }else{
        next();
      }
    });

機能しますが、OWASPでは、OPTIONSを公開しないことをお勧めします。バックエンド/ホスティングサービス(Nginx、Apache)などで耐候性を
保つ

0

プリフライトは、ブラウザによって実装されるWebセキュリティ機能です。Chromeの場合、-disable-web-securityフラグを追加して、すべてのWebセキュリティを無効にすることができます。

例: "C:\ Program Files \ Google \ Chrome \ Application \ chrome.exe" --disable-web-security --user-data-dir = "C:\ newChromeSettingsWithoutSecurity"。最初にクロムの新しいショートカットを作成し、そのプロパティに移動して、上記のようにターゲットを変更できます。これは役立つはずです!


機能を有効にするためだけに、OPがクライアントにブラウザのセキュリティをオフにするように指示することは本当に期待できませんよね?!
svarog

@svarogこれは主に開発目的であり、主に本番サーバーではこの問題に直面しません。
Arijit Patra

ブラウザがスローしていて、バックエンドでHttpメソッドOPTIONSがブロックされている場合、OPTIONSが失敗したため、ブラウザがPOST / PUTの対応するAPIを呼び出さないような効果がありますか?
Pサティシュパトロ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.