ゲートウェイのクロスドメイン処理

クロスドメインとは

クロスオリジンとは、ブラウザーにおいて、Web アプリケーションがそのページとは異なるオリジンのリソースにアクセスしようとすると、ブラウザーがこの動作にセキュリティ制限を課し、ユーザー データのセキュリティを保護するために一部のクロスオリジン リクエストを阻止することを意味します。

ブラウザーが同一生成元ポリシーに従うという制限の下では、同じソースからのスクリプトは同じソースの下のリソースにのみアクセスでき、他のソースの下のリソースにはアクセスできません。同一生成元ポリシーは、クロスドメイン リクエストを制限することで、悪意のある Web サイトがユーザーの機密情報を盗んだり、クロスサイト スクリプティング攻撃 (XSS) やクロスサイト リクエスト フォージェリ (CSRF) などの手段を通じてその他の悪意のある動作を実行したりすることを防ぎます。

一般に、リクエストのプロトコル、ホスト、ポートのいずれかが現在のページのソース (つまり、プロトコル、ホスト、ポート) と異なる場合、そのリクエストはクロスドメインリクエストとみなされます。

クロスドメインによって引き起こされる問題

クロスドメインリクエストは、主にセキュリティ上の理由から、同一オリジンポリシーによって制限されています。同一オリジン ポリシーは、クロスドメイン リクエストによる他のソースへの読み取りアクセスを制限し、悪意のある Web サイトによるユーザー データの盗用を防ぎます。この制限により、クロスドメイン要求が直接実行されなくなり、次の問題が発生します。

AJAX 要求が拒否されました: ブラウザーは、クロスオリジン要求で XMLHttpRequest オブジェクトを使用する通信をブロックします。
Cookie は利用できません: クロスドメイン要求では、デフォルトでは元のサイトの Cookie 情報が送信されないため、ユーザーの身元を確認することができません。
アクセスが拒否されました: クロスオリジン要求はサーバーのアクセス制御ポリシーによってブロックされる可能性があります。

ゲートウェイはクロスドメインの問題を解決します

ゲートウェイは、クライアントとバックエンド サービスの間にある中間層サービスです。リクエストの転送、ルーティング、プロトコル変換を担当し、クロスドメイン処理のソリューションを提供します。Gateway がクロスドメインの問題を解決する主な方法は次のとおりです。

リバース プロキシ: ゲートウェイはバックエンド サービスのリバース プロキシとして機能し、クライアントのリクエストをターゲット サービスに転送できます。ゲートウェイとバックエンド サービスは同じドメイン内にあるため、クロスドメインの問題は発生しません。
クロスドメイン リソース共有 (CORS): ゲートウェイは、特定のドメイン下のリクエストに対するクロスドメイン アクセスを許可する CORS ポリシーを構成できます。応答ヘッダーに Access-Control-Allow-Origin フィールドを追加することで、クロスドメイン アクセスを実現するクロスドメイン要求を許可するドメイン名を指定します。
JSONP プロキシ: ゲートウェイは JSONP プロキシとして機能し、サーバー側でターゲット サービスへのリクエストを開始し、コールバック関数にラップされた応答データをクライアントに返します。動的に作成される

クロスドメイン比較を解決するその他の方法

ここに画像の説明を挿入します

コード例

@Component
@Order(2)
public class CorsResponseHeaderFilter implements GlobalFilter {
    
    


    private static final String ANY = "*";


    @Override
    @SuppressWarnings("serial")
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
    
    
            exchange.getResponse().getHeaders().entrySet().stream()
                    .filter(kv -> (kv.getValue() != null && kv.getValue().size() > 1))
                    .filter(kv -> (kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)
                            || kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)
                            || kv.getKey().equals(HttpHeaders.VARY)))
                    .forEach(kv ->
                    {
    
    
                        // Vary只需要去重即可
                        if(kv.getKey().equals(HttpHeaders.VARY)) {
    
    
                            kv.setValue(kv.getValue().stream().distinct().collect(Collectors.toList()));
                        } else{
    
    
                            List<String> value = new ArrayList<>();
                            if(kv.getValue().contains(ANY)){
    
      //如果包含*,则取*
                                value.add(ANY);
                                kv.setValue(value);
                            }else{
    
    
                                value.add(kv.getValue().get(0)); // 否则默认取第一个
                                kv.setValue(value);
                            }
                        }
                    });
        }));
    }
}

このコードでは、GlobalFilter インターフェイスを実装し、@Component アノテーションを使用することで、クラスをグローバル フィルターとして登録します。また、@Order(2) アノテーションを使用してフィルターの実行順序を指定します。

filter メソッドでは、まずchain.filter(exchange) が呼び出され、リクエストが次のフィルターまたはターゲット サービスに転送されて処理されます。次に、then メソッドと Mono.fromRunnable を使用して新しい Mono を作成し、リクエストの完了後にいくつかの操作を実行します。

この新しい Mono では、応答オブジェクト ServerHttpResponse を取得し、応答ヘッダーのキーと値のペアを走査します。一部の特定の応答ヘッダーについては、次の処理を実行します。

Access-Control-Allow-Origin、Access-Control-Allow-Credentials、Vary の 3 つの応答ヘッダーについて、それらの値が存在するかどうか、およびその長さが 1 より大きいかどうか (つまり、複数の値が存在するかどうか) を判断します。条件が合えばそれに応じて対応させていただきます。
Vary ヘッダーの場合、その値は重複排除されます。つまり、重複した値が削除されます。
Access-Control-Allow-Origin ヘッダーまたは Access-Control-Allow-Credentials ヘッダーの場合は、その値を 1 つの要素のみを含む新しいリストに設定します。
元の値にワイルドカード文字 * が含まれている場合、新しいリストには要素 * が 1 つだけ含まれます (つまり、ワイルドカード文字は変更されません)。
それ以外の場合、新しいリストには元の値の最初の要素のみが含まれます (つまり、変更されないままになります)。
これらのプロセスを通じて、クロスドメイン要求の応答ヘッダーをフィルタリングして変更し、要件を満たす応答ヘッダーがクロスドメイン要求で返されるようにし、クライアントがクロスドメイン リソースに正常にアクセスできるようにします。

まとめと改善

クロスドメインは、Web スクリプトが異なるドメイン名のリソースにアクセスすることを制限するためにブラウザーで使用されるセキュリティ メカニズムです。同一生成元ポリシーでは、Web スクリプトは、Web スクリプトが配置されている Web ページと同じプロトコル、ドメイン名、およびポートを持つリソースにのみアクセスできることが要求されます。この制限は、ユーザーのプライバシーとセキュリティを保護し、悪意のある Web サイトがユーザーの機密情報を取得するのを防ぐことを目的としています。

クロスドメイン要求の問題を解決するために、ブラウザーはクロスドメイン リソース共有 (CORS) などのメカニズムを提供します。CORS を使用すると、サーバーは応答に特定の HTTP ヘッダーを設定して、他のドメイン名からのリソースへのアクセス要求を承認できます。応答ヘッダーに Access-Control-Allow-Origin フィールドを追加すると、サーバーはアクセスを許可するドメイン名を指定できます。このようにして、ブラウザーは応答ヘッダーの設定に基づいてクロスドメイン要求を許可するかどうかを決定できます。

CORS 以外にも、JSONP など、クロスドメイン リクエストを解決する方法があります。動的に作成されたJSONP

クロスドメインは一般的な開発問題であり、開発者がクロスドメインの原理と解決策を理解することが重要です。CORS やその他のクロスドメイン ソリューションを合理的に使用することで、ユーザーのセキュリティを保護しながら、異なるドメイン名間のデータ対話を実現できます。

おすすめ

転載: blog.csdn.net/weixin_45309155/article/details/133207739