UFO ET IT

서블릿에서 클라이언트의 원격 주소를 어떻게 얻습니까?

ufoet 2020. 11. 20. 17:24
반응형

서블릿에서 클라이언트의 원격 주소를 어떻게 얻습니까?


서버로 들어오는 클라이언트의 원래 IP 주소를 얻을 수있는 방법이 있습니까? 나는 사용할 수 request.getRemoteAddr()있지만 항상 프록시 또는 웹 서버의 IP를 얻는 것 같습니다.

클라이언트가 나에게 연결하는 데 사용하는 IP 주소를 알고 싶습니다. 어쨌든 내가 그것을 얻을 수 있습니까?


이 시도:

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;  
    }  

request.getRemoteAddr()방법입니다. 프록시가 소스 IP를 변경하는 것 같습니다. 일부 프록시는 일부 사용자 지정 http 헤더에 원래 IP를 추가합니다. 관심있는 항목이 없는지 확인하기 위해 모두 사용 request.getHeaderNames()하고 request.getHeaders(name)인쇄하십시오. 마치 X-CLIENT-IP(그거 만들었지 만 이렇게 생겼어요)


내가 사용한 최고의 솔루션

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;      
} 

의미있는 방식으로이를 수행 할 수 없습니다.

프록시는 proxied-for 헤더를 추가 할 수도 있고 추가하지 않을 수도 있지만 대부분의 경우이 주소는 어쨌든 내부 전용 주소이므로 의미가 없습니다. 조직의 가장자리에있는 대부분의 프록시는 어쨌든 네트워크 내부에 대해 가능한 한 적게 드러내도록 구성됩니다.

이 정보를 어떤 용도로 사용 하시겠습니까?


이것은 일반적으로 응용 프로그램 문제가 아닌 배포 문제이므로 다른 접근 방식은 응용 프로그램 컨테이너를 적절하게 구성하는 것입니다. 일단 구성되면 컨테이너는 적절한 헤더를 검사하고 애플리케이션은 request.getRemoteAddr().

예를 들어 Tomcat에서는 원격 IP 밸브를 사용할 수 있습니다 . 대부분의 응용 프로그램 서버에는 비슷한 기능이 있다고 가정합니다.

컨테이너는 또한 프런트 엔드로드 밸런서가 SSL 연결을 종료하고 HTTP를 통해 요청을 앱 서버로 전달하는지 여부를 파악할 수 있습니다. 이는 애플리케이션이 자체에 대한 URL을 생성해야 할 때 중요합니다.


이와 같은 더 우아한 솔루션을 사용하지 않는 이유는 무엇입니까?

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);
}

코드를 중복 제거하십시오!


"x-forwarded-for"요청 헤더에는 프록시 또는로드 밸런서를 사용하는 경우 원래 클라이언트 IP가 포함됩니다. 그러나 모든 proxies / lb가이 헤더를 추가하는 것은 아니라고 생각합니다.

다음은 헤더를 구문 분석하는 자바 코드입니다. http://www.codereye.com/2010/01/get-real-ip-from-request-in-java.html

이 헤더가 없으면 @Bozho가 제안한대로 진행합니다.


String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null) {
            ipAddress = request.getHeader("X_FORWARDED_FOR");
            if (ipAddress == null){
                ipAddress = request.getRemoteAddr();
            }
        }

Why I think we should try to get IP from header 'X-Forwarded-For' first? If you get from request.getRemoteAddr(), it could be client's real ip or last proxy's ip which forwards the request. Thus we can't tell which condition it belongs to. However, if 'X-Forwarded-For' is set into the header, client ip is bound to be the left-most part of what you get from it.

    /**
     * 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 "";
    }

InetAddress inetAddress = InetAddress.getLocalHost();
String ip = inetAddress.getHostAddress();

참고URL : https://stackoverflow.com/questions/4678797/how-do-i-get-the-remote-address-of-a-client-in-servlet

반응형