Java/Spring

[ERROR] javax.servlet.ServletRequest.getRemoteAddr() is not supported

코딩공부 2023. 6. 28. 20:13

[이슈 당시 상황]

Back단 java application, Front단 react, nextjs를 사용해서 프로젝트를 진행 AWS EC2 인스턴스로 배포 하고, Route 53으로 DNS 연결을 하고 ACM 으로 SSL 연결 해당 EC2를 443 포트로 로드밸런싱을 처리

 

[이슈 내용]

특정 IP만 접속 가능하도록 설정 해두었는데, 해당 IP으로 접근이 되지 않고 javax.servlet.ServletRequest.getRemoteAddr() is not supported 에러가 발생.

 

[해결 방안]

일반적으로 Spring Security의 인증 과정에서 HttpServletRequest를 사용하여 클라이언트의 IP 주소를 가져올 수 있습니다. 그러나 특정 환경에서는 getRemoteAddr() 메서드가 지원되지 않을 수 있습니다. 이는 프록시 서버 또는 로드 밸런서와 같은 중간 장치를 통해 애플리케이션 서버에 연결되는 경우가 일반적인 시나리오입니다.

 

로드 밸런서를 통해 클라이언트의 IP 주소를 가져오는 방법에는 두 가지가 있습니다.

  1. X-Forwarded-For 헤더 사용: 일반적으로 로드 밸런서는 X-Forwarded-For 헤더에 클라이언트의 IP 주소를 포함하여 전달합니다. 따라서 이 헤더를 사용하여 클라이언트의 IP 주소를 가져올 수 있습니다. 위의 코드에서 request.getHeader("X-Forwarded-For")를 사용하여 이 값을 가져오고 있습니다. 이 방법은 로드 밸런서에서 올바르게 설정되어 있을 경우에 동작합니다.
  2. request.getRemoteAddr() 사용: 일부 경우에는 로드 밸런서를 통해 전달된 클라이언트의 IP 주소를 request.getRemoteAddr() 메서드를 통해 직접 얻을 수 있습니다. 그러나 이 방법은 로드 밸런서의 구성 및 환경에 따라 다를 수 있습니다. 몇 가지 가능한 이유는 다음과 같습니다:
    • 로드 밸런서가 클라이언트의 IP 주소를 실제 요청으로 전달하지 않을 수 있습니다.
    • 로드 밸런서의 구성이나 방화벽 설정으로 인해 request.getRemoteAddr() 메서드가 로드 밸런서의 IP 주소를 반환할 수 있습니다.

 

로드밸런싱으로 서버를 연결하게 되어서 IP를 가져올 수가 없어서  에러 발생 

 

java Security config 설정에 구문 추가 해서 처리

 

 @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/images/**").permitAll() // 파일 다운로드 컨트롤러는 모든 IP 주소에서 접근 허용
                .antMatchers(PERMIT_URL_ARRAY).permitAll() // swagger array 접근 허용
                .requestMatchers(request -> {
                    String clientIpAddress = request.getHeader("X-Forwarded-For");
                    if (clientIpAddress == null || clientIpAddress.isEmpty() || "unknown".equalsIgnoreCase(clientIpAddress)) {
                        clientIpAddress = request.getRemoteAddr();
                    } else {
                        // X-Forwarded-For 헤더는 클라이언트 IP 주소들을 쉼표(,)로 구분하여 전달합니다.
                        // 첫 번째 IP 주소가 클라이언트의 실제 IP 주소입니다.
                        int index = clientIpAddress.indexOf(',');
                        if (index != -1) {
                            clientIpAddress = clientIpAddress.substring(0, index);
                        }
                    }
                    String finalClientIpAddress = clientIpAddress;
                    return Arrays.stream(allowIps).anyMatch(ip -> ip.equals(finalClientIpAddress));
                }).permitAll() // IP 접근 가능
                .anyRequest().denyAll()
                .and()
            .csrf().disable(); // CSRF 보안 비활성화 (필요에 따라 활성화 설정 가능)
    }

 

'Java > Spring' 카테고리의 다른 글

Spring에서 @Transactional  (0) 2025.03.12
Proxy 패턴  (0) 2025.03.12
@Transactional 적용 안된 현상 정리  (0) 2022.04.09
Controller parameter 받는 방법  (0) 2022.04.09
ERROR - java.lang.OutOfMemoryError: Java heap space  (0) 2021.09.16