web-dev-qa-db-ja.com

サーブレットでクライアントのリモートアドレスを取得するにはどうすればよいですか?

サーバーに来るクライアントの元のIPアドレスを取得する方法はありますか? request.getRemoteAddr()を使用できますが、常にプロキシまたはWebサーバーのIPを取得しているようです。

クライアントが私に接続するために使用しているIPアドレスを知りたいと思います。とにかくそれを手に入れることができますか?

63
grassbl8d

これを試して:

public static String getClientIpAddr(HttpServletRequest request) {  
        String ip = request.getHeader("X-Forwarded-For");  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("Proxy-Client-IP");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("WL-Proxy-Client-IP");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("HTTP_CLIENT_IP");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getRemoteAddr();  
        }  
        return ip;  
    }  
102

request.getRemoteAddr()が道です。プロキシがソースIPを変更するようです。一部のプロキシがそれを行うと、カスタムHTTPヘッダーに元のIPが追加されます。 request.getHeaderNames()request.getHeaders(name)を使用し、それらをすべて印刷して、関心のあるものがないかどうかを確認します。 X-CLIENT-IP(それを作成しましたが、このように見えます)

10
Bozho

私が今まで使用した中で最高のソリューション

public String getIpAddr(HttpServletRequest request) {      
   String ip = request.getHeader("x-forwarded-for");      
   if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {      
       ip = request.getHeader("Proxy-Client-IP");      
   }      
   if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {      
       ip = request.getHeader("WL-Proxy-Client-IP");      
   }      
   if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {      
       ip = request.getRemoteAddr();      
   }      
   return ip;      
} 
5
Ali Hashemi

これを意味のある方法で行うことはできません。

プロキシはプロキシ対象ヘッダーを追加する場合としない場合がありますが、多くの場合、これは内部専用アドレスであるため、ユーザーにとっては意味がありません。とにかく、組織のエッジにあるほとんどのプロキシは、ネットワークの内部についてできるだけ公開しないように構成されています。

この情報を何に使うつもりですか?

4
time4tea

これは通常、アプリケーションの問題ではなく展開の問題であるため、別のアプローチはアプリケーションコンテナを適切に構成することです。構成が完了すると、コンテナは適切なヘッダーの検査を行い、アプリケーションは引き続きrequest.getRemoteAddr()を使用します。

たとえば、Tomcatでは Remote IP Valve を使用できます。ほとんどのアプリケーションサーバーには同様の機能があると思います。

コンテナは、フロントエンドロードバランサーがSSL接続を終了し、HTTP経由でアプリサーバーにリクエストを転送しているかどうかを把握することもできます。これは、アプリケーションがそれ自体へのURLを生成する必要がある場合に重要です。

4
craigforster

このようなよりエレガントなソリューションを使用しないのはなぜですか?

private static final List<String> IP_HEADERS = Arrays.asList("X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR");

public static String getClientIpAddr(HttpServletRequest request) {
    return IP_HEADERS.stream()
        .map(request::getHeader)
        .filter(Objects::nonNull)
        .filter(ip -> !ip.isEmpty() && !ip.equalsIgnoreCase("unknown"))
        .findFirst()
        .orElseGet(request::getRemoteAddr);
}

コードを重複排除します!

1
whitebrow

「x-forwarded-for」リクエストヘッダーには、プロキシまたはロードバランサーを使用している場合、元のクライアントIPが含まれます。しかし、すべてのプロキシ/ lbがこのヘッダーを追加するとは限りません。

ここで、ヘッダーを解析するためのコードJavaコード: http://www.codereye.com/2010/01/get-real-ip-from-request-in-Java。 html

このヘッダーが存在しない場合は、@ Bozhoが示唆するように進めます

1
Emilio

最初にヘッダー '_X-Forwarded-For_'からIPを取得する必要があると思うのはなぜですか? request.getRemoteAddr()から取得する場合、 クライアントの実際のIPまたはリクエストを転送する最後のプロキシのIP になります。したがって、どの条件に属しているかわかりません。ただし、ヘッダーに '_X-Forwarded-For_' が設定されている場合、クライアントIPは、そこから取得したものの左端の部分にバインドされます。

_    /**
     * Try to get real ip from request:
     * <ul>
     *     <li>try X-Forwarded-For</li>
     *     <li>try remote address</li>
     * </ul>
     *
     * @param request    request
     * @return real ip or ""
     */
    private String tryGetRealIp(HttpServletRequest request) {
        // X-Forwarded-For: <client>, <proxy1>, <proxy2>
        // If a request goes through multiple proxies, the IP addresses of each successive proxy is listed.
        // This means, the right-most IP address is the IP address of the most recent proxy and
        // the left-most IP address is the IP address of the originating client.
        String forwards = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotBlank(forwards)) {
            // The left-most IP must be client ip
            String ip = StringUtils.substringBefore(forwards, ",");
            return ip;
        } else if (StringUtils.isNotBlank(request.getRemoteAddr())) {
            // this could be real client ip or last proxy ip which forwards the request
            return request.getRemoteAddr();
        }
        return "";
    }
_
0
puppylpg
String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null) {
            ipAddress = request.getHeader("X_FORWARDED_FOR");
            if (ipAddress == null){
                ipAddress = request.getRemoteAddr();
            }
        }
0
Srinivasu