Nginx はクロスドメインの問題を簡単に解決します

クロスドメインの問題が発生した場合は、すぐにコピーして試すことを選択しないでください。処理する前にこの記事を詳しくお読みください。それがあなたのお役に立てると信じています。

# 分析前の準備:

フロントエンド Web サイトのアドレス: http://localhost:8080

サーバーURL: http://localhost:59200 

まず、サーバーがクロスドメインを処理していないことを確認し、次に、最初に postman を使用してサーバー インターフェイスをテストするのが通常です。

Web サイト 8080 がサーバー インターフェイスにアクセスすると、クロスドメインの問題が発生します。どのように解決すればよいでしょうか? 次に、ドメイン全体で発生するさまざまな状況をすべてリストし、nginx プロキシを通じて解決します (原理を理解している限り、背景は同じです)。

クロスドメインには主に 4 つの応答ヘッダーが含まれます。

  • Access-Control-Allow-Origin は、クロスドメイン リクエストを許可する送信元アドレスを設定するために使用されます (クロスドメインの場合、プリフライト リクエストと公式リクエストが検証されます)。

  • Access-Control-Allow-Headers ドメイン間での伝送が許可される特別なヘッダー フィールド (プリフライト リクエストでのみ検証される)

  • Access-Control-Allow-Methods クロスドメインで許可されたリクエスト メソッドまたは HTTP 動詞 (プリフライト リクエスト検証のみ)

  • Access-Control-Allow-Credentials でドメイン間での Cookie の使用を許可するかどうか。ドメイン間で Cookie を使用する場合は、値を true に設定してこの要求応答ヘッダーを追加できます (設定の有無は、ただし、クロスドメイン時に Cookie を送信するかどうかのみですが、設定されている場合は、事前チェック リクエストと正式なリクエストの両方を設定する必要があります)。ただし、クロスドメインの使用は、代替手段が多数あるため、必要な場合を除いて推奨されません (プロジェクトで使用されていますが、不安定で、一部のブラウザーでは使用できません)。

インターネット上の多くの記事では、これらのレスポンスヘッダ情報を Nginx に直接追加することでクロスドメイン問題を解決できると書かれています。もちろん、ほとんどのケースは解決できますが、まだ多くのケースがあると思います。明確に構成されており、クロスドメインの問題も報告されます。

プリフライトリクエストとは何ですか? : クロスドメイン条件が発生すると、ブラウザはまずサーバーに、現在の Web ページのドメイン名がサーバーの許可リストに含まれているかどうか、およびどの HTTP 動詞とヘッダー フィールドを使用できるかを尋ねます。肯定的な応答を受信した場合にのみ、ブラウザは正式な XMLHttpRequest リクエストを発行します。それ以外の場合は、エラーが報告されます。以下に示すように

実践的なシミュレーションを開始します。

Nginx プロキシ ポート: 22222、次のように構成

server {
   
           listen       22222;        server_name  localhost;        location  / {
   
               proxy_pass  http://localhost:59200;        }}

プロキシが成功したかどうかをテストするには、Nginx プロキシ ポート 2222 を介してインターフェイスに再度アクセスします。次の図に示すように、プロキシを通過した後もインターフェイスに正常にアクセスできることがわかります。

次に、Web サイト 8080 を使用して、Nginx プロキシの背後にあるインターフェイス アドレスにアクセスします。エラー レポートは次のとおりです↓↓↓

# ケース 1: 

オリジン「http://localhost:8080」から「http://localhost:22222/api/Login/TestGet」の XMLHttpRequest へのアクセスが CORS ポリシーによってブロックされました: プリフライト要求への応答がアクセス制御チェックに合格しません: いいえ「Access-Control-Allow-Origin」ヘッダーが要求されたリソースに存在します。

エラー メッセージからエラーを明確に特定できます (赤色の部分に注意してください)。プリフライトは、プリフライトであることを示します。クロスドメイン CORS メカニズムは、最初にプリフライト (OPTIONS リクエスト) を実行し、実際のリクエストはリクエストは、リクエストが成功するまで送信されません。これは、サーバーが CORS 標準を認識し、CORS をサポートしていないレガシー サーバーを保護するように設計されています。

エラー メッセージから、プリフライト リクエストのリクエスト レスポンス ヘッダーに Access-Control-Allow-Origin が欠落していることがわかります。間違いがある場合は変更できます。Nginx の設定情報を次のように変更します (赤い部分が追加部分です)。不足しているものを埋めます。非常にシンプルで明確です。

server {
   
           listen       22222;        server_name  localhost;        location  / {
   
              add_header Access-Control-Allow-Origin 'http://localhost:8080';           proxy_pass  http://localhost:59200;         }    }

ははは、解決できるかもしれないと喜びに満ちていたとき、まだ同じ問題を報告していることに気づきました。

ただし、構成には何も問題はありません。問題は Nginx にあります。以下のリンクは http://nginx.org/en/docs/http/ngx_http_headers_module.html です。

 

add_header ディレクティブは、リターン ヘッダー フィールドを追加するために使用されます。ステータス コードが図に示されているものである場合にのみ有効です。各応答メッセージのヘッダー フィールド情報を伝えたい場合は、最後に always を追加する必要があります (テスト後、Access-Control-Allow-Origin ヘッダー情報のみ always を追加し、その他のヘッダー情報は追加する必要はありません)常に持ち戻されます)、それでは試してみましょう

server {
   
           listen       22222;        server_name  localhost;        location  / {
   
              add_header Access-Control-Allow-Origin 'http://localhost:8080' always;           proxy_pass  http://localhost:59200;         }    }

設定を変更したところ反映されました もちろんクロスドメインでは解決しませんでしたが、エラーレポートの内容が変更されたため上記の問題は解決しました。

# ケース 2:

オリジン「http://localhost:8080」から「http://localhost:22222/api/Login/TestGet」の XMLHttpRequest へのアクセスが CORS ポリシーによってブロックされました: プリフライト要求への応答がアクセス制御チェックに合格しません: HTTP OK ステータスがありません。

エラーメッセージプロンプトから、クロスドメインブラウザのデフォルト動作であるプレリクエスト(オプションリクエスト)がokステータスコードを受信して​​いないことが分かりますので、この時点で設定ファイルを修正してください。オプション要求の場合、ステータス コードをブラウザに返します (通常は 204)。

 server {
   
           listen       22222;        server_name  localhost;        location  / {
   
              add_header Access-Control-Allow-Origin 'http://localhost:8080' always;           if ($request_method = 'OPTIONS') {
   
                   return 204;           }           proxy_pass  http://localhost:59200;         }    }

設定が完了すると、エラーメッセージが変更されていることがわかります。

# ケース 3:

オリジン「http://localhost:8080」から「http://localhost:22222/api/Login/TestGet」の XMLHttpRequest へのアクセスが CORS ポリシーによってブロックされました: リクエスト ヘッダー フィールドの承認は Access-Control-Allow によって許可されていません- プリフライト応答のヘッダー。

これは、リクエスト前の応答ヘッダー Access-Control-Allow-Headers にヘッダー情報の承認が欠落していることを意味します (状況はさまざまに異なります。クロスドメイン後、カスタムで追加されたヘッダー情報は許可されないため、ヘッダー情報をヘッダー情報に追加する必要があります)要求応答ヘッダー Access-Control-Allow-Headers により、このヘッダー情報の伝達がサーバーによって合法であるとブラウザが認識されるようになります。ここで伝達するのは承認であり、その他はトークンである可能性があります。不足しているものを追加してください)、問題はわかっているので、構成ファイルを変更し、対応する欠落部分を追加して、もう一度試してください。

server {
   
           listen       22222;        server_name  localhost;        location  / {
   
              add_header Access-Control-Allow-Origin 'http://localhost:8080' always;           if ($request_method = 'OPTIONS') {
   
                  add_header Access-Control-Allow-Headers 'authorization'; #为什么写在if里面而不是接着Access-Control-Allow-Origin往下写?因为这里只有预检请求才会检查               return 204;           }         proxy_pass http://localhost:59200;     }}

この時点で、エラー報告の問題が状況 1 に戻っていることがわかります。

add_header が if ($request_method = 'OPTIONS') に記述されている限り、プリフライト リクエストの場合、外部設定は無効になることがテストおよび検証されています。↓↓。

公式ドキュメントには次のように書かれています。

複数の add_header ディレクティブが存在する可能性があります。これらのディレクティブは、現在のレベルで add_header ディレクティブが定義されていない場合にのみ、前のレベルから継承されます。

これは、現在のレベルに add_header 命令がない場合、前のレベルの add_header を継承することを意味します。逆に、現在のレイヤに add_header がある場合、前のレイヤの add_header を継承することはできません。

 構成は次のように変更されます。

server {
   
           listen       22222;        server_name  localhost;        location  / {
   
               add_header Access-Control-Allow-Origin 'http://localhost:8080' always;            if ($request_method = 'OPTIONS') {
   
                   add_header Access-Control-Allow-Origin 'http://localhost:8080';                add_header Access-Control-Allow-Headers 'authorization';                return 204;            }            proxy_pass  http://localhost:59200;         }    }

現時点では、クロスドメインの問題は修正後に解決されました。

ただし、上記でクロスドメインの問題は解決しましたが、今後Nginxのバージョンが更新される可能性を考慮すると、このルールが変更されるかどうかはわかりません。起源、これも同様です。後述するように、許可されていません。したがって、構成は次のように適切に変更されます。

server {
   
           listen       22222;        server_name  localhost;        location  / {
   
               if ($request_method = 'OPTIONS') {
   
                   add_header Access-Control-Allow-Origin 'http://localhost:8080';                add_header Access-Control-Allow-Headers 'authorization';                return 204;            }            if ($request_method != 'OPTIONS') {
   
                   add_header Access-Control-Allow-Origin 'http://localhost:8080' always;            }            proxy_pass  http://localhost:59200;         }    }

まだ終わっていないので、引き続きチャットしましょう↓↓

# ケース 4:

以前の API では POST リクエストと GET リクエストのみを使用できますが、Access-Control-Allow-Methods リクエスト応答ヘッダーのクロスドメインでは、デフォルトで POST と GET のみがサポートされます。他のリクエスト タイプが表示されると、クロスドメイン例外も発生します。

たとえば、ここではリクエストする API インターフェースのリクエストメソッドを元の GET から PUT に変更し、起動後に再試行します。コンソールでエラーがスローされます。

オリジン「http://localhost:8080」から「http://localhost:22222/api/Login/TestGet」の XMLHttpRequest へのアクセスが CORS ポリシーによってブロックされました: メソッド PUT は Access-Control-Allow-Methods によって許可されていませんプリフライト応答で。

エラーレポートの内容も非常に明確です。このプレリクエストでは、クロスドメインでの PUT メソッドの使用が許可されていません。Access-Control-Allow-Methods の構成を変更する必要があります (不足しているものを追加) 、ここでは PUT のみを追加します。自分で追加できます)、サーバーが許可されていることをブラウザーに知らせます

server {
   
       listen 22222;    server_name localhost;    location / {
   
           if ($request_method = 'OPTIONS') {
   
               add_header Access-Control-Allow-Origin 'http://localhost:8080';            add_header Access-Control-Allow-Headers 'content-type,authorization';            add_header Access-Control-Allow-Methods 'PUT';#为这么只加在这个if中,不再下面的if也加上?因为这里只有预检请求会校验,当然你加上也没事。            return 204;        }        if ($request_method != 'OPTIONS') {
   
               add_header Access-Control-Allow-Origin 'http://localhost:8080' always;        }        proxy_pass http://localhost:59200;    }}

ここで、PUT タイプに変更した後、Access-Control-Allow-Headers リクエスト レスポンス ヘッダーは自動的に content-type リクエスト ヘッダーを検証することに注意してください。これはケース 3 と同じであり、これだけで十分です。ない。content-type が追加されていない場合、次のエラーが報告されます。(単純にしたい場合は、Access-Control-Allow-Headers と Access-Control-Allow-Methods を * に設定できます。これは、それらがすべて一致することを意味します。ただし、Access-Control-Allow-Origin を に設定することはお勧めしません。 ※セキュリティ上の理由から、ドメイン名を制限する必要があります。)

すべて追加すると、問題は解決します。ここで報告された 405 は、サーバーのインターフェイスが GET に対してのみオープンしており、PUT に対してはオープンしていないことを示しています。現時点では、PUT メソッドを使用してこのインターフェイスをリクエストしているため、インターフェイスはこのステータスコードを返します。

 

# ケース 5:

最後に、別の状況について説明します。つまり、バックエンドがクロスドメインを処理するため、自分で処理する必要はありません (ここでは、一部のバックエンド エンジニアがサーバー コードを変更して、クロスドメインを自分で解決します) , しかし、彼らは原理を理解していません、オンラインで見つけてください コードの一部が貼り付けられ、その結果、応答情報の処理が不完全になります. たとえば、メソッドが完全に追加されていない場合、ヘッダーはポイントに追加されません,私が使用したものには実際のプロジェクトで使用したものが含まれていない可能性があり、オプション「Wait」を追加せずにリクエストによって返されたステータス コードにより、Nginx が共通の構成を使用することになり、次の例外が報告される可能性があります)

オリジン「http://localhost:8080」から「http://localhost:22222/api/Login/TestGet」の XMLHttpRequest へのアクセスが CORS ポリシーによってブロックされました:「Access-Control-Allow-Origin」ヘッダーには複数のヘッダーが含まれています値 '*, http://localhost:8080' ですが、許可されるのは 1 つだけです。

これは、現時点では、複数の Access-Control-Allow-Origin 要求応答ヘッダーが返されますが、許可されるのは 1 つだけであることを意味します。この場合、もちろん、Access-Control-Allow-Origin 構成を削除するように構成を変更します。この場合、クロスドメインの問題を単独で解決するには、Nginx 構成とサーバーのいずれか 1 つだけを選択することをお勧めします。

(ここで、上記の書き方に従った場合、if $request_method = 'OPTIONS' の Access-Control-Allow-Origin は削除できません。事前チェック リクエストの場合は !='OPTIONS' を削除するだけです。これは直接返され、リクエストは 59200 サービスに転送されません。これも削除された場合は、ケース 1 と同じエラーが報告されます。では、なぜクロスドメインを解決する必要があると言えるのでしょうか。サーバー コード レベルで問題を解決するか、Nginx プロキシを使用して問題を解決しますか? 混ぜてください。そうしないと、原理を理解していない人がインターネットでコードを見つけても問題を解決できない可能性があります)

 ↓ ↓ ↓ ↓ ↓

次に、完全な構成を投稿します (* 番号は独自の設定に従って入力されます)。

server {
   
           listen       22222;        server_name  localhost;        location  / {
   
               if ($request_method = 'OPTIONS') {
   
                   add_header Access-Control-Allow-Origin 'http://localhost:8080';                add_header Access-Control-Allow-Headers '*';                add_header Access-Control-Allow-Methods '*';                add_header Access-Control-Allow-Credentials 'true';                return 204;            }            if ($request_method != 'OPTIONS') {
   
                   add_header Access-Control-Allow-Origin 'http://localhost:8080' always;                add_header Access-Control-Allow-Credentials 'true';            }            proxy_pass  http://localhost:59200;         }    }

または:

server {
   
           listen       22222;        server_name  localhost;        location  / {
   
               add_header Access-Control-Allow-Origin 'http://localhost:8080' always;            add_header Access-Control-Allow-Headers '*';            add_header Access-Control-Allow-Methods '*';            add_header Access-Control-Allow-Credentials 'true';            if ($request_method = 'OPTIONS') {
   
                   return 204;            }            proxy_pass  http://localhost:59200;         }    }

最後に、これはクロスドメインの問題を解決するプロセスです。よく読んでいただければ、理解しやすく、実際に使用する際に自分で問題を解決できると思います。皆さんのお役に立てれば幸いです。上記の内容です。すべて私自身のテストコードの理解に基づいていますので、間違った理解があれば修正してください。

おすすめ

転載: blog.csdn.net/leonnew/article/details/123895626