Nginx は、https 構成やブラウザー https の安全でない問題の処理だけでなく、ドメイン間のクロスで遭遇するさまざまな問題と解決策も処理します。

記事ディレクトリ


序文

提示:本人在生产部署服务时遇到一系列跨域问题和https配置问题,特此做以下记录:

はじめに 1. クロスドメインとは何ですか?

クロスドメインとは、ページ a がページ b のリソースを取得したいことを意味します。ページ a とページ b のプロトコル、ドメイン名、ポート、およびサブドメイン名が異なる場合、またはページ a が IP アドレスでページ b がドメイン名アドレスの場合、すべてのアクセス アクションはクロスドメインであり、ブラウザは通常、セキュリティ上の理由からクロスドメイン アクセスを制限します。つまり、クロスドメイン リソース要求は許可されません。

はじめに 2. クロスドメイン生成の条件は何ですか?

注意:跨域限制访问,其实是浏览器的限制。理解这一点很重要。所以,当用java(或者其他语言)调用RESTful api,从来不会报什么跨域错误
ここに画像の説明を挿入


クロスドメイン処理に一般的に使用される 2 つの方法

1. Springboot はクロスドメインの問題にどのように対処しますか?

1.1 コントローラ内の個別構成

@CrossOrigin クロスドメイン アノテーションを各コントローラー クラスに追加します

1.2 @configation クラスのグローバル構成

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
    
    
        registry.addMapping("/**")  // 匹配了所有的URL
                .allowedHeaders("*")  // 允许跨域请求包含任意的头信息
                .allowedMethods("*")  // 设置允许的方法
                .allowedOrigins("*")  // 设置允许跨域请求的域名
                .allowCredentials(true);  // 是否允许证书,默认false
    }
}

1.3 フィルターに応答ヘッダーを追加する

protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
    
    
    res.addHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
    res.addHeader("Access-Control-Allow-Methods", "*");
    res.addHeader("Access-Control-Allow-Headers", "Accept,Authorization,DNT,Content-Type,Referer,User-Agent");
    res.addHeader("Access-Control-Allow-Credentials","true"); // 允许携带验证信息
    chain.doFilter(req, res);
}

2. nginx はクロスドメインの問題をどのように処理しますか?

2.1 Nginx サーバーの応答ヘッダー パラメーターを構成する

403 クロスドメイン エラーが発生し、要求されたリソースに「Access-Control-Allow-Origin」ヘッダーが存在しない場合は、Nginx サーバーの応答ヘッダー パラメーターを構成する必要があります。

location / {
    
      
    add_header Access-Control-Allow-Origin *; //允许所有请求访问
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; //允许访问的请求类型
    add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
	//预检请求需要用到
    if ($request_method = 'OPTIONS') {
    
    
        return 204;
    }
}

2.2. 各パラメータの詳細な解釈

  1. アクセス制御許可オリジン
服务器默认是不被允许跨域的,给Nginx服务器配置`Access-Control-Allow-Origin *`后,表示服务器可以接受所有的请求源(Origin),即接受所有跨域的请求。
  1. Access-Control-Allow-Headers は、次のエラーを防ぐためのものです。
Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

このエラーは、現在のリクエスト Content-Type の値がサポートされていないことを示します。実際、これは「application/json」というタイプのリクエストを開始したことが原因でした。ここには、プリフライト リクエスト (プリフライト リクエスト) という概念が関係しています。以下の「プリフライト リクエスト」の概要を参照してください。

  1. Access-Control-Allow-Methods は、次のエラーを防ぐためのものです:
    Content-Type は、プリフライト応答の Access-Control-Allow-Headers によって許可されていません。

  2. OPTIONS に 204 return を追加することで、POST リクエストを送信するときに Nginx が依然としてアクセスを拒否するというエラーに対処します。

发送"预检请求"时,需要用到方法 OPTIONS ,所以服务器需要允许该方法。

Nginx 構成ドメイン名が複数のドメイン名にまたがる

方法 1: nginx 組み込み変数を使用する (一般的に使用される)

server {
    
    
        set $cors '';
        if ($http_origin ~* "^http://deomain01:port$") {
    
    
            set $cors $http_origin;
        }
        if ($http_origin ~* "^http://deomain02:port$") {
    
    
            set $cors $http_origin;
        }
        if ($http_origin ~* "^http://deomain002:port$") {
    
    
            set $cors $http_origin;
        }
        location /live{
    
    
                  ...
                add_header 'Access-Control-Allow-Origin' '$cors';
                add_header 'Access-Control-Allow-Credentials' 'true';
                # 为预检请求加的header
                add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';
                #为预检请求加的header
                add_header 'Access-Control-Allow-Headers' '*';
        }

説明: $http_origin の形式は、nginx がリクエストのヘッダーの XXX の値を取得するためのものです。
ここではオリジンが取得され、一般的なクロスドメインリクエストはリクエストのソースをオリジンに置きます(ブラウザはオリジンのヘッダーをクロスドメインリクエストのヘッダーに追加します) $ cors 変数は目的のクロスドメインを取得し
ますドメイン名を取得し、「 add_header 'Access-Control-Allow-Origin' '$cors'」に割り当てます。

方法 2: マップを使用する

  map $http_origin $cors_list{
    
    
		default  http://aaa.cn;
	    "~ http://bbb.cn"  http://bbb.cn;
	}
    server {
    
    
        listen       8089;
        server_name  localhost;
        location /live{
    
    
                  ...
                add_header 'Access-Control-Allow-Origin' '$cors_list';
                add_header 'Access-Control-Allow-Credentials' 'true';
                # 为预检请求加的header
                add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';
                #为预检请求加的header
                add_header 'Access-Control-Allow-Headers' '*';
        }

説明:
マップコマンドは、デフォルトで nginx によってロードされる ngx_http_map_module モジュールによって提供されます。

语法: map $var1 $var2 {
    
    }
默认值: -
配置段: http

map为一个变量设置的映射表。映射表由两列组成,匹配模式和对应的值。

在map块里的参数指定了源变量值和结果值的对应关系。

default: 没有匹配结果将使用的默认值。如果没有设置default,将会用一个空的字符串作为默认的结果。

匹配模式可以是一个简单的字符串或者正则表达式,使用正则表达式要用(‘~’)

方法 3: 第 3 レベルのドメイン名の通常の一致

   location / {
    
    

             if ($http_origin ~* (http?://.*\.aliuncle\.top$)) {
    
    
                    add_header Access-Control-Allow-Origin $http_origin;
            }
            index index.php;
            try_files $uri $uri/ /index.php?$args;
    }

注: nginx.conf 構成ファイルでクロスドメインを構成する場合は、ブラウザーのキャッシュなどのクライアントを必ずクリアしてください。そうしないと、構成が有効になりません。

2.3、nginx はクロスドメイン プロセスで発生したさまざまなエラー レポートを処理します

1. クロスドメイン要求は ID 認証情報 Cookie エラーを送信できません ()

ここに画像の説明を挿入

問題の説明: いずれにせよ、ID 認証情報 Cookie をリクエストで渡すことができません

解決策:
フロントエンド:
1. フロントエンドがリクエストするときに、リクエスト オブジェクトの属性 withCredentials を true に設定します。
ここに画像の説明を挿入

2. バックエンドは、応答ヘッダー Credentials を true としてサポートします
ここに画像の説明を挿入
注意:除了 Access-Control-Allow-Credentials 之外,跨域发送 Cookie 还要求 Access-Control-Allow-Origin 不允许使用通配符。 事实上不仅不允许通配符,而且 只能指定单一域名:
。それ以外の場合は、クロス エラーが報告されます。
ここに画像の説明を挿入

2.4、プリフライトリクエスト(プリフライトリクエスト)エラー

ここに画像の説明を挿入

はじめに:
Cross-Origin Resource Sharing (CORS) 標準では、新しい HTTP ヘッダー フィールドのセットが追加され、サーバーがどのオリジン サイトにどのリソースへのアクセス許可があるかを宣言できるようになります。さらに、仕様では、サーバー データに副作用を及ぼす可能性のある HTTP リクエスト メソッド (特にGET 以外の HTTP リクエスト、または特定の MIME タイプを使用した POST リクエスト) について、ブラウザは最初に OPTIONS メソッドを使用してプリフライト リクエストを開始する必要があります。 (プリフライトリクエスト)サーバーがクロスドメインリクエストを許可しているかどうかを知るため。サーバーが許可を確認した後、実際の HTTP リクエストが開始されます。プリフライト要求を返す際、サーバーは、アイデンティティ資格情報 (Cookie および HTTP 認証関連データを含む) を伝送するかどうかをクライアントに通知することもできます。
実際、Content-Type フィールドが application/json であるリクエストは、特定の MIME タイプを持つ上記の POST リクエストですが、CORS では、次の MIME タイプに属さない Content-Type はすべて事前チェック リクエストであると規定されています。

application/x-www-form-urlencoded
multipart/form-data
text/plain

2.4.1. 予想されるリクエストプロセス (最初にオプションリクエスト/レスポンスを送信し、次にポストリクエストを送信)

ここに画像の説明を挿入

2.4.2、事前チェックリクエストエラー

Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

説明:
application/json リクエストは、正式な通信の前に「事前チェック」リクエストを追加します。この「事前チェック」リクエストはヘッダー情報をもたらします。サーバーが応答するとき、返されたヘッダー情報に Access-Control が含まれていない場合は、 - Allow-Headers: Content-Type は、デフォルト以外の Content-Type が受け入れられないことを示します。つまり、上記のエラーが発生します。

预检请求头信息
Access-Control-Request-Headers: Content-Type:
OPTIONS /api/test HTTP/1.1
Origin: http://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type

2.4.3. 事前チェックリクエストのエラーレポートを解決するにはどうすればよいですか?

プリフライトリクエストについても前述しましたが、オプションリクエストに遭遇したときにnginxが処理成功ステータスコードを返すように、nginxプロキシの前に判断を追加するだけで済みます。

//预检请求需要用到
    if ($request_method = 'OPTIONS') {
    
    
        return 204;
    }

nginxステータスコードの詳しい説明

httpの詳しい説明

2.4.4 Access-Control-Allow-Origin は 1 回のみ設定でき、バックエンドで設定した後は、nginx で再度設定することはできません

次のエラーが報告されます。
ここに画像の説明を挿入
説明: ブラウザーは 1 つの値のみを受け入れ、空にすることはできないため、サーバーから返される Access-Control-Allow-Origin 値はリストであってはなりません。

2.5. リクエストヘッダーには、認可などの追加情報が含まれます。

ここに画像の説明を挿入

报错:(リクエスト ヘッダー フィールドの承認は、プリフライトの Access-Control-Allow-Headers によって許可されていません)

2.5.1、説明

応答ヘッダー Access-Control-Allow-Headers はプリフライト リクエスト (プリフライト リクエスト) で使用され、正式なリクエストの Access-Control-Request-Headers フィールドに表示されるヘッダー情報をリストします。単純なヘッダーなどの単純なヘッダー、Accept、Accept-Language、Content-Language、Content-Type (application/x-www-form-urlencoded、multipart/form-data、または text/plain の 3 つの MIME 値に限定)型の解析後 (パラメーターを除く)、それらは常にサポートされており、このヘッダーに特にリストする必要はありません。

Authorization や x-token などの追加のリクエスト ヘッダー情報を許可する必要があります。このエラーは、リクエスト ヘッダーの Authorization が許可されていないことを知るために、リクエストの前処理を通じてレポートされるため、クロスドメインが報告されます。

2.5.2. 解決する

許可されたヘッダー Authorization を追加する必要があり、リクエストメソッドがオプションであると判断された場合、クライアントに ok (200) を返すことで、正式なポストリクエストを続行できます。

    add_header 'Access-Control-Allow-Origin' '*' always;
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, DELETE, PUT, OPTIONS';
	add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, X-Custom-Header, Access-Control-Expose-Headers, Token, Authorization';
	add_header 'Access-Control-Allow-Headers'  '*';
    add_header 'Access-Control-Max-Age' 1728000;

2.6. 新しいバージョンの Google におけるクロスドメイン エラーの詳細な分析と解決: リクエスト クライアントは安全なコンテキストではなく、リソースはよりプライベートなアドレスにあります

2.6.1 エラー報告の理由

エラー: 安全でないリクエスタがよりプライベートなローカル リソースをリクエストしました
ここに画像の説明を挿入

理由: Google バージョン 94 以降、Google は安全でない Web サイトのプライベート ネットワークを更新し、より多くのプライベート リソースへのアクセスを求めるリクエストをブロックしました。同時に、プライベート ネットワーク リソースを要求する前に、OPTIONS プリフライト要求が最初に送信されます。

2.6.2 解決策

1. Google 以外のカーネル ブラウザ (Firefox、edge などを使用) を置き換えるか、バージョンを下げます。

2. Google Chrome の設定を変更する 解決策
: 設定を無効にする Google Chrome バージョン 94 ~ 101 の場合、http Web サイトから送信されるプライベート リソースへのリクエストが正常に送信されるようにブラウザの設定を変更できます。

次のように進めます。

ステップ 1: ブラウザに「chrome://flags/#block-insecure-private-network-requests」と入力します。

ステップ 2: [安全でないプライベート ネットワーク要求をブロックする] 項目のデフォルトを [無効] に変更し、ブラウザを再起動します (バージョンが異なると設定が異なります。詳細については、次の参考リンクを参照してください)。リンク 3 を参照してください。イントラネットの写真やその他のリソース
ここに画像の説明を挿入

すべて https アクセスを使用すると問題を根本的に解決できます

httpsの設定方法(nginxでsslを設定する)

1. 構成

次の手順を要約します。 ssl を適用する -> サーバーに ssl ファイル ストレージを適用する -> nginx で ssl を設定する

  server {
    
    
                listen       8002 ssl;          
                server_name temp.3zyun.com ;   #公网ip      115.148.208.122                                       
                client_max_body_size 1024M;
                ssl_certificate /usr/local/nginx/yjssl/7604469_temp.3zyun.com_nginx/7604469_temp.3zyun.com.pem;
        ssl_certificate_key /usr/local/nginx/yjssl/7604469_temp.3zyun.com_nginx/7604469_temp.3zyun.com.key;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on ;
                location / {
    
    
                         
                        proxy_pass http://bpm-server/;
                        proxy_set_header Host $host:$server_port;
                }
        }

注意 :端口后面要加上ssl才可生效
ssl 構成はこの記事からインスピレーションを受けました

2. 遭遇した一連の問題

2.1. h5 プロジェクトがパッケージ化され、実稼働環境にデプロイされます。


ここに画像の説明を挿入
混合コンテンツ: 「xxx」のページは HTTPS でロードされましたが、安全でないリソース「xxx」を要求しました。このリクエストはブロックされました。コンテンツは HTTPS で提供する必要があります。 問題解決の説明: ブラウザが「上にロードされました」のように表示される場合「HTTPS ですが、安全でないリソース/フレームが要求されました」エラーは、一般に、当社の Web サイトが HTTPS で、相手のリンクが HTTP プロトコルであるため、Ajax または JavaScript がリクエストした場合、http インターフェースをリクエストしている場合、または http リソースをインポートしている場合は、上記のエラーが報告されます。 https では直接ブロック (ブロック) され、ブラウザーはデフォルトでこの動作を安全ではないものとしてブロックします。

解決:

(在index.html的head中加入以下代码)
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />

機能: このタグを追加する原理は、META タグを使用して http リクエストを https (SSL プロトコル) リクエストに強制的に変換することです。

要約する

常にピットを踏んで必ず成長する!

おすすめ

転載: blog.csdn.net/wei1359765074410/article/details/127510086