본문 바로가기
프로그래밍/Java

Java로 Client IP 찾는 방법

by KHRDev 2022. 5. 23.

Java로 개발을 하다 보면 로그인 이력을 남기거나 하는 상황에 Client IP를 데이터베이스에 Insert 하는 로직을 만들어야 하는 경우가 생길 수 있다.. 크게 2가지의 방법이 존재하는데 하나하나 설명해볼까 한다.


 

1. InetAddress

import java.net.InetAddress;
import java.net.UnknownHostException;

public static String getClientIP(HttpServletRequest req) throws UnknownHostException {
	InetAddress clientAddress = InetAddress.getLocalHost();
    	ip = clientAddress.getHostName() + "/" + address.getHostAddress();
    
    	return ip;
}

허나 위의 방식으로 개발을 하게 되면 로컬 서버에서 접속을 하였을 때 나의 Client IP는 잘 찾지만 서버에 배포하게 되면 Proxy 서버를 거치게 되면서 배포한 서버 IP가 Client로 잡혀 배포한 서버 IP가 나오게 된다.

 

위의 문제점에 대한 대안으로 Client IP를 구하는 표준

2. request.getHeader("X-Forwarded-For");

public static String getClientIp(HttpServletRequest req) {
	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.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;
}

사실상 Client IP를 구하는 표준이다. Client가 서버에 request를 보낼 때 request 헤더에 "X-Forwarded-For" 키로 

IP를 담아 보내게 된다.

 

이것도 문제점이라고 할 수도 있는... 한 가지 문제점이 존재하는데 서버에 배포된 서비스에서는 Client IP를 잘 찾지만 

로컬에서 접속을 하였을 때 IPv4 또는 IPv6으로 Client IP를 "0:0:0:0:0:0:0:1"을 잡게 되거나 "127.0.0.1"를 잡게 되는 상황이 생기게 된다.

그러므로 가장 이상적으로 IP를 찾는 방법은...

 

3. 혼합..

import java.net.InetAddress;
import java.net.UnknownHostException;

public static String getClientIp(HttpServletRequest request) throws UnknownHostException {
    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.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(); 
    }

    if(ip.equals("0:0:0:0:0:0:0:1") || ip.equals("127.0.0.1")) 
    {
        InetAddress address = InetAddress.getLocalHost();
        ip = address.getHostName() + "/" + address.getHostAddress();
    }

    return ip;
}

1번과 2번의 방법을 적절히 혼합하여 사용하는 방법이 될 수 있겠다.

 

3번과 같이 적절히 혼합하여 getClientIP라는 메서드로 모듈화 하여 사용하게 된다면 

로컬 서버로 접속하였을 때와 배포된 서버로 접속하였을 경우 적절하게 Client IP를 찾아올 수 있을 것이다...

'프로그래밍 > Java' 카테고리의 다른 글

ModelMapper란?  (0) 2023.07.12
[Java] StringTokenizer에 대해 알아보자~  (0) 2022.08.09
String vs (StringBuffer vs StringBuilder)  (0) 2022.06.07
Java에서 문자열 앞뒤 공백 제거  (0) 2022.05.31
++i vs i++  (0) 2022.05.18

댓글