오류 세부 정보
현재 톰캣은 프록시 서버로 기능하는 ALB뒤에 있기에 애플리케이션은 오직 HTTP요청만 받고 있습니다.
HTTPS 요청은 ALB에서 끝나고, ALB는 톰캣과 소통을 HTTP로 합니다.
해당 문제를 구글링해서 찾은 스택 오버플로우 링크입니다.
https://stackoverflow.com/questions/64403718/spring-redirect-happening-to-http-login-instead-of-https-logi
첫번째 댓글에 따라
를 application.properties에 추가해주고
import org.springframework.core.Ordered;
import org.springframework.web.filter.ForwardedHeaderFilter;
@Bean
FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
final FilterRegistrationBean<ForwardedHeaderFilter> filterRegistrationBean = new FilterRegistrationBean<ForwardedHeaderFilter>();
filterRegistrationBean.setFilter(new ForwardedHeaderFilter());
filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filterRegistrationBean;
}
ForwardedHeaderFilter-Bean 도 구성에 추가해주니 문제가 해결됐습니다.
근데 이게 다 뭘까요?
공식문서 를 해석해보았습니다.
톰캣을 서블릿 컨테이너로 사용시, 스프링 부트는 환경설정을 감지하면 톰캣만의 RemoteIpValve를 자동적으로 추가합니다.
또한, 비록 프록시 서버가 SSL Termination을 담당하긴 하지만, "HttpServeletRequest"에 의존하여 안전성을 판단합니다. 기준이 되는 행동은 특정 request header(x-forwarded-for, x-forwarded-proto)의 존재 혹은 부재에 따라 결정됩니다. 이들의 이름은 conventional하기 때문에 대부분의 앞단 프록시에서 작동합니다. application.properties에 밑의 값을 추가하여 valve를 켤 수 있습니다.
server.tomcat.remote-ip-header=x-forwarded-for
server.tomcat.protocol-header=x-forwarded-proto
위의 특성이 존재하면 밸브가 켜집니다.
x-forwarded-for 헤더는 로드밸런서(프록시)를 통해 웹 서버에 접속하는 클라이언트의 "원 IP"주소를 식별하는 헤더입니다. 트래픽이 로드밸런서나 프록시를 거치면 서버 로그에는 중간단계의 IP주소만이 남기 때문에 클라이언트의 원 IP주소를 보기 위해서 해당 헤더가 사용됩니다.
x-forwarded-proto는 클라이언트가 로드밸런서에 접속할 때 사용했던 프로토콜-http 혹은 https -를 확인하는 헤더입니다. 마찬가지로 서버 로그에 클라이언트와 로드 밸런서간 사용된 프로토콜은 포함돼 있지 않기 때문에 이를 확인하기 위하여 해당 헤더가 사용되어집니다.
한마디로 안정성과 권한을 체크할 시, 실제 클라이언트 ip주소와 요청 프로토콜을 사용하겠단 뜻으로 보입니다.
security.oauth2.client.pre-established-redirect-uri는 OAuth2 클라이언트를 위한 리디렉션 URI를 설정하는 특성입니다. 이 값을 통해 브라우저는 해당 uri로 리디렉션합니다.
security.oauth2.client.registered-redirect-uri 는 authorization server에 등록된 리디렉션 URI를 설정하는 특성입니다.
애플리케이션이 켜지면 authorization server에 등록될 리디렉션 uri들을 설정합니다.
security.oauth2.client.use-current-uri 를 false로 두어 현재 request의 URI를 리디렉션 uri로 사용하지 않습니다. 대신, authorization server에 있는 리디렉션 URI값으로 리다이렉트 합니다.
server.use-forward-headers 는 proxy-forwarded 헤더를 신뢰할 것인지에 대한 특성입니다. true로 설정하여 프록시 서버에서 전달된 헤더를 통해서 클라이언트의 주소를 결정합니다.
로드밸런서에게서 넘어온- 수정을 거친 - 값을 확인하고, 이 값에 x-forwarded-for 과 x-forwarded-proto를 적용하여 원 값을 추출해 내는것으로 이해했습니다. 이 특성을 false로 두면 프록시로부터 수정되온 값을 아예 무시할 것입니다.
server.tomcat.use-relative-redirects 는 애플리케이션의 HttpServletResponse가 리다이렉트 응답시 relative URL 을 쓸지, absoulte URL을 쓸지 결정합니다. true이기 때문에 client에게 보내지는 리다이렉트 url은 http나 https:// 혹은 포트 번호등을 포함하지 않습니다. 대신 리다이렉트 url은 path와 쿼리 파라미터만을 포함합니다.
리다이렉트 url을 건내줄때, 앞뒤의 별칭들(www. / org. 등)을 고려하여 true로 둔 것으로 이해했습니다
server.tomcat.internal-proxies 는 server.use-forward-headers가 true일때, 클라이언트의 IP주소를 결정하는 과정에서 신뢰할 internal proxies를 구성하는데 사용됩니다. X-forwarded-for를 포함하고있는, 내부 프록시를 거친 요청을 판단하는데 쓰입니다.
import org.springframework.core.Ordered;
import org.springframework.web.filter.ForwardedHeaderFilter;
@Bean
FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
final FilterRegistrationBean<ForwardedHeaderFilter> filterRegistrationBean = new FilterRegistrationBean<ForwardedHeaderFilter>();
filterRegistrationBean.setFilter(new ForwardedHeaderFilter());
filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filterRegistrationBean;
}
해당 코드는 ForwardedHeaderFilter타입의 FilterRegistrationBean 빈을 만듭니다. 이 빈은 서블렛 컨테이너에 필터로 등록되고, 이 필터는 애플리케이션에 들어오는 모든 요청에 적용됩니다.
ForwardedHeaderFilter 는 프록시 서버를 통해 더해진 헤더로부터 정보를 얻기 위한 필터입니다.
이 정보를 가지고 클라이언트가 보낸 값과 함께 request 헤더를 구성합니다.
해당 필터에서 앞서 설명했던 X-Forwarded-Proto 헤더를 request.scheme 와 request.secure 특성을 채우는데 사용합니다.
이를 거쳐서 URL의 안전한 버전(https)를 사용할지 아닐지가 결정됩니다.
따라서 애플리케이션이 http를 리턴하는지와 상관없이, 프록시를 거쳐온 https 요청은 https로 다뤄지게 됩니다.