본문으로 바로가기
반응형

일반적인 웹 개발을 할 때에 서버에 접속한 클라이언트의 IP를 가져오는 것은 필수이다.

로그인 이력 등의 로그성 데이터에 있어서 클라이언트 IP는 가장 중요한 정보이기 때문이다.


Spring MVC 기반의 서버에서 개발할 때에 컨트롤러에서 받은 HttpServletRequest 객체를 사용하면 간단하게 IP를 얻을 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    @RequestMapping("/login.do")
    private ModelAndView doLogin(@Valid LoginVO loginVO, BindingResult result,
            RedirectAttributes redirect, HttpServletRequest request, HttpServletResponse response) throws Exception {
        /*
         * 로그인 처리 SVC 호출
         * */
        loginVO.setLoginIp(request.getRemoteAddr());
        String loginRslt = loginSvc.doLogin(loginVO);
        /*
         * 분기
         * Login성공
         * */
        if(loginRslt.equals(StaticStringUtil.USER_LOGIN_SUCCESS)){
            return new ModelAndView("redirect:/moveMain.do");
        }else{
            return new ModelAndView("login/login""loginErr", loginRslt);
        }
        
    }
cs


위 코드처럼 request.getRemoteAddr()로 클라이언트의 ip를 얻어올 수 있었다.


하지만 얻어온 정보는 0:0:0:0:0:0:0:1 로, 이는 IPv6 형식의 값이다.

대부분의 프로젝트에서 원하는 IP 형식은 우리가 흔히 아는 127.0.0.1과 같은 IPv4 형식의 값일 것이다.


이를 위해서는 서버 구동시 vm arguments로 -Djava.net.preferIPv4Stack=true 를 주면 IPv4형식을 얻을 수 있다.


vm arguments를 준 뒤 가져온 ip는 IPv4 형식임을 확인할 수 있다.




(이클립스에서 vm arguments 설정하는 법)


cmd에서 구동할 경우는 문제가 없지만 이클립스에서 arguments를 주려고 할 때 방법을 몰라 당황했다.

run -> run configurations 에서 구동하려는 프로젝트를 선택하고, Arguments 탭에서 값을 줄 수 있다. VM arguments 이외에도 일반 Program arguments도 줄 수 있다.





여기에 더해 그냥 HttpServletRequest 객체의 getRemoteAddr() 메소드만을 사용하여 ip를 얻어올 경우에 문제가 있을 경우가 있다고 한다.

1. 프록시를 거쳐서 들어오는 접속의 경우, 정확한 ip정보를 가져올 수 없다.

2. was가 2차 방화벽 안에 있고 클라이언트에서 web server를 통해 호출하는 경우 getRemoteAddr은 진짜 접속한 클라이언트의 ip가 아닌, 웹서버의 ip 정보를 가져온다.

3. 클러스터로 구성도외 load balancer에서 호출되는 경우도 getRemoteAddr은 load balancer의 ip를 가져온다.


이걸 해결하기 위해 HTTP Header 를 확인하여 분기를 통해 처리한다.


구글링한 코드를 참조하여 일반적으로 쓸 수 있는 유틸을 만들어서 사용했다.

(proxy나 웹로직 서버의 경우까지 처리할 수 있다)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ClientUtils {
 
    public static String getRemoteIP(HttpServletRequest request){
         String ip = request.getHeader("X-FORWARDED-FOR"); 
         
         //proxy 환경일 경우
         if (ip == null || ip.length() == 0) {
             ip = request.getHeader("Proxy-Client-IP");
         }
 
         //웹로직 서버일 경우
         if (ip == null || ip.length() == 0) {
             ip = request.getHeader("WL-Proxy-Client-IP");
         }
 
         if (ip == null || ip.length() == 0) {
             ip = request.getRemoteAddr() ;
         }
         
         return ip;
    }
}
cs


위 코드와 같은 유틸을 만들어 두고, 클라이언트의 ip가 필요할 때에 request.getRemoteAddr() 대신 ClientUtils.getRemoteIP(request) 를 호출하면 되겠다.





반응형

 Other Contents