Java は IP アドレスを取得します。request.getHeader("x-forwarded-for")

Nginxの設定

フロントエンドとバックエンドを分離した上で、静的サーバーとしてnginxを使用し、リバースプロキシ方式によりクロスドメインインターフェースを実現することで、開発コストを削減する一方で、調達コストなど多くの問題を抱えています。クライアントの実際の IP の。

リスク管理や支払いプロセスなどの一部の特殊なシナリオでは、ユーザーの IP 情報を取得する必要があることがよくありますが、nginx リバース プロキシはサーバーのリクエストのソースを完全に変更し、ユーザーとサーバー間の接続を分離しながら実現します。クロスドメイン、以下に示すように

ユーザーがフロントエンド ページ「https://a.test.com/index/html」にアクセスして支払いインターフェイスを呼び出すと、支払いインターフェイスのアドレスは「https://a.test.com/goPay」になります。 、その後、nginx プロキシによってサーバー側の「https://b.test.com/goPay」に反転されますこのとき、サーバー側にとって、受信するリクエストはすべて nginx サーバーからのものであり、サーバー側が取得するデフォルトの IP は nginx サーバーの IP です。これは私たちが望んでいることではありません。現時点では、次の構成を追加する必要があります。

 
 
  1. proxy_set_header X-Real-IP $remote_addr;

  2. proxy_set_header X-Real-Port $remote_port;

  3. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

3 つのヘッダーは次を表します。

 
 
  1. X-Real-IP 客户端ip

  2. X-Real-Port 客户端或上一级端口

  3. X-Forwarded-For 包含了客户端和各级代理ip的完整ip链路

このうち、X-Real-IP は必須で、最後の 2 つの項目はオプションです。nginx プロキシのレベルが 1 つだけの場合、X-Real-IP と X-Forwarded-For は一致します。プロキシのレベルが複数ある場合、X-Forwarded-For は次の形式になります。

X-Forwarded-For: 客户端ip, 一级代理ip, 二级代理ip...

X-Forwarded-For はクライアント IP を取得するプロセスではオプションですが、セキュリティ上の問題が発生したときにログ ファイルに従ってソースを追跡できるように、個人的には保持しておくことをお勧めします。

穴があります:

上記の設定部分に加えて、ネチズンはホストヘッダーも提供しました

proxy_set_header Host $host;

まず第一に、このヘッダーは必要ありません。第二に、ホスト ヘッダーと proxy_pass 転送によって生成されたホスト ヘッダーが競合し、その結果インターフェイス 502 が発生します。ただし、この構成を更新した後は、テストで nginx -t を使用するなど、nginx を再起動してもエラーは報告されません。

ジャワ取得

シナリオ: サーバーがクライアント要求を受信すると、通常、署名検証、クライアント IP 制限などを実行する必要があります。クライアント IP 制限を実行するときは、最初に実際の IP を取得する必要があります。一般に次の 2 つの状況に分けられます。

方法 1: クライアントはプロキシを使用せずにサーバー (nginx、squid、haproxy) に直接アクセスします。

方法 2: クライアントはマルチレベル プロキシを通過し、最終的にサーバー (nginx、squid、haproxy) に到達します。

  クライアント要求情報は HttpServletRequest に含まれており、クライアント IP は getRemoteAddr() メソッドを通じて取得できます。このとき、方法 1 を使用している場合は、クライアントの実 IP を直接取得できます。また、方法 2 のプロキシ形式の場合、この時点でマルチレベル リバース プロキシの後、メソッド getRemoteAddr() ではクライアントの実 IP を取得できず、転送されたリクエスト情報は x- で取得できます。転送されました。クライアント要求が転送されると、IP が追加され、カンマで区切られます (例: 10.47.103.13,4.2.2.2,10.96.112.230)。

 リクエスト内のパラメータ:

request.getHeader("x-forwarded-for") : 10.47.103.13,4.2.2.2,10.96.112.230

request.getHeader("X-Real-IP") : 10.47.103.13

request.getRemoteAddr():10.96.112.230

クライアント アクセスが転送されると、IP が追加され、カンマで区切られます。最終的な正確な顧客情報は次のとおりです。

  • x-forwarded-for が空でない場合、それはカンマの前の最初の IP です。
  • X-Real-IP が空でない場合、それは IP です。
  • それ以外の場合は getRemoteAddr();

コード例:

 
 

  このとき、通常の状況では、クライアントの実際の IP を取得できます。なお、サーバー側の負荷の形態については、x-forwarded-forを設定して保存する必要があります。現在のロード形式には、haproxy、nginx、その他の形式が含まれます。構造図は次のとおりです。

 /** 
     * 获取用户真实IP地址,不使用request.getRemoteAddr()的原因是有可能用户使用了代理软件方式避免真实IP地址, 
     * 可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值 
     *  
     * @return ip
     */
    private String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for"); 
        System.out.println("x-forwarded-for ip: " + ip);
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {  
            // 多次反向代理后会有多个ip值,第一个ip才是真实ip
            if( ip.indexOf(",")!=-1 ){
                ip = ip.split(",")[0];
            }
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("Proxy-Client-IP");  
            System.out.println("Proxy-Client-IP ip: " + ip);
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("WL-Proxy-Client-IP");  
            System.out.println("WL-Proxy-Client-IP ip: " + ip);
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("HTTP_CLIENT_IP");  
            System.out.println("HTTP_CLIENT_IP ip: " + ip);
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");  
            System.out.println("HTTP_X_FORWARDED_FOR ip: " + ip);
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("X-Real-IP");  
            System.out.println("X-Real-IP ip: " + ip);
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getRemoteAddr();  
            System.out.println("getRemoteAddr ip: " + ip);
        } 
        System.out.println("获取客户端ip: " + ip);
        return ip;  
    }

おすすめ

転載: blog.csdn.net/u010919402/article/details/130075954