Spring Hateoas links https 스키마 적용
Proxy Server나 Load Balancer를 통해 Restful API Service로 요청을 하면 Hateoas links의 스키마가 https
가 아닌 http
로 생성되는 현상이 있습니다. 이를 해결 하는 방법에 대해 알아보겠습니다.
Nginx에서 X-Forwarded-Proto
를 Restful API Service로 전달합니다.
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Prefix $http_x_forwarded_prefix;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-NginX-Proxy true;
proxy_redirect off;
charset utf-8;
proxy_pass http://api-backend;
}
Restful API Service에서 다음과 같이 hateoas links를 생성합니다.
public CompanyModel toModel(Company entity) {
return entity.toModel()
.add(getSelfLink(entity.getCmpnyCd()));
}
...
private Link getSelfLink(String cmpnyCd) {
return linkTo(methodOn(CompanyController.class)
.detailCompany(cmpnyCd))
.withSelfRel()
.withType(HttpMethod.GET);
}
페이지 요청의 Response 결과
{
"_embedded":{
"companyModelList":[
{
"cmpnyCd":"1017006750",
"cmpnyNm":"테스트",
"bizMemNo":"1234567890",
"dfltAddr":"서울 종로구 사직로 161 경복궁",
"_links":{
"self":{
"href":"http://api주소/v1/company/1017006750",
"type":"GET"
}
}
},
...
]
},
"_links":{
"first":{
"href":"http://api주소/v1/company/query?page=0&size=10"
},
"self":{
"href":"http://api주소/v1/company/query?page=0&size=10"
},
"next":{
"href":"http://api주소/v1/company/query?page=1&size=10"
},
"last":{
"href":"http://api주소/v1/company/query?page=100&size=10"
}
},
"page":{
"size":10,
"totalElements":100,
"totalPages":100,
"number":0
}
}
응답에서 href가 https가 아닌 http
로 설정된 것을 확인할 수 있습니다.
그림 출처: https://tomgregory.com/spring-boot-behind-load-balancer-using-x-forwarded-headers/
이런 현상을 해결 하기 위해서 위 그림 처럼 Spring에서 ForwardedHeaderFilter을 등록하면 해결됩니다.
Proxy Server(Nginx)
Spring Cloud Gateway
Spring framework 5.0~ 또는 Spring Boot 2.0 ~
Spring Security
Spring cloud gateway
application.yml
server:
forward-headers-strategy: native
Spring service
application.yml
server:
forward-headers-strategy: native
forward-headers-strategy: native
는 proxy server 또는 load-balancer에서 넘겨준 forward-headers 값을 그대로 사용하도록 합니다.
forwardedHeaderFilter 등록
@Configuration
public class WebConfig implements WebMvcConfigurer {
...
@Bean
public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
FilterRegistrationBean<ForwardedHeaderFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new ForwardedHeaderFilter());
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
}
댓글남기기