본문 바로가기
카테고리 없음

[Java] 클라이언트(접속자)의 IP주소 가져오기

클라이언트(접속자)의 IP주소 가져오기

개발을 하다보면 클라이언트의 IP를 확인할 경우가 있습니다. 당연히 Java에서도 이에 대한 기능을 제공하는 클래스가 있는데 이 클래스를 그냥 사용하기에는 몇가지 넘어야 하는 산(?)이 있어서 그에 대해 알아보고자 포스팅을 작성합니다.

 

 

 

 

1. 사용자 IP가져오기

public String getUserIp() throws Exception {

    String ip = null;
    HttpServletRequest request = 
    ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();

    ip = request.getRemoteAddr();

    return ip;
}

 

일반적으로 사용자의 IP를 가져오는 코드입니다. 하지만 위의 코드에는 문제가 있습니다. 평상시에 이클립스와 톰켓을 활용한 개발테스트에서는 정상적으로 작동될지 모르나 실제로 was에 배포를 하게되는 경우에는 보통 was앞단에 Load balancers나 Proxy server, Caching server등등이 있는데 이들이 클라이언트와 Was사이에서 요청이나 응답을 가공하여 전달하기 때문에 request.getRemoteAddr()함수로 IP를 얻을 경우 Proxy나 기타 다른 이이피를 얻게 되기 때문입니다.

 

이러한 문제를 해결하기 위해 등장한게 X-Forwarded-For 헤더 입니다. X-Forwarded-For헤더에는 프록시와 같은 아이피도 들어있지만 맨 첫번째에 실제 클라이언트의 아이피가 들어가 있기 때문에 클라이언트의 아이피를 확인할 때 먼저 X-Forwarded-For헤더가 있는지 확인한 후 없을경우에 위의 코드에서 사용한 request.getRemoteAddr()로 IP를 얻으면 됩니다. 

 

하지만 문제가 또 있습니다...

모든 제품이 X-Forwarded-For헤더를 사용하면 좋겠지만 다른 헤더를 사용하는 제품이 있기 때문에 몇가지 번거로운 작업을 통해 IP를 여러번 추출해야만 합니다. 아래 코드를 통해서 모든 종류의 헤더에 대한 IP추출하는 방법을 확인할수 있습니다.

 

	public String getUserIp() throws Exception {
		
        String ip = null;
        HttpServletRequest request = 
        ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();

        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.getHeader("X-Real-IP"); 
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
            ip = request.getHeader("X-RealIP"); 
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
            ip = request.getHeader("REMOTE_ADDR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
            ip = request.getRemoteAddr(); 
        }
		
		return ip;
	}

 

 

 

 

 

 

2. IPv6주소 형식에서 IPv4형식으로 변환하기

아직 한가지 고비가 더 남았습니다. Java는 IPv6와 IPv4를 모두 사용할 수 있는 환경에서 IPv6형식을 사용하지만 아직까지 IPv4형식의 IP주소가 더 익숙한 사람들이 대부분이기 때문에 IPv4형식의 주소를 원한다면 그에 대한 변환과정을 해야합니다.

 

 

우선 이클립스에서 Run- Run Configurations에 들어간다음 위의 이미지처럼 톰캣 서버를 선택후 VM arguments에 -Djava.net.preferIPv4Stack=true 를 추가한 후 적용하면 됩니다.

 

만약 개발이 아닌 실제 배포환경에서 설정을 하기위해서는 Was서버에 해당설정을 해줘야 하는데 그에 대한 설명은 이 포스팅에서는 생략하도록 하겠습니다.

 

 

 

 

 

 

 

 

 

댓글