I have a Spring Boot java app deployed on heroku. I want to be sure that my registration endpoint can be only accessed by https. So far I've known, heroku uses load balancer which redirect every https connection to http with a special header (X-forwarded-porto).
Iam using
compile("org.springframework.boot:spring-boot-starter-security")
tomcat:
remote_ip_header: x-forwarded-for
protocol_header: x-forwarded-proto
@Controller
@RequestMapping("/users")
public class AccountController {
@Autowired
private AccountRepository accountDao;
@RequestMapping(value = "/register", method = RequestMethod.POST, consumes = "application/json")
public ResponseEntity<Resource<Account>> createAccount(@RequestBody @Valid Account account) { ... }
Actually I've found a solution ( finally ) in this repo https://github.com/fenrirx22/springmvc-https-enforcer.
Created 2 classes:
@Configuration
public class ApiConfig {
@Bean
public Filter httpsEnforcerFilter(){
return new HttpsEnforcer();
}
}
and:
public class HttpsEnforcer implements Filter {
private FilterConfig filterConfig;
public static final String X_FORWARDED_PROTO = "x-forwarded-proto";
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
if (request.getHeader(X_FORWARDED_PROTO) != null) {
if (request.getHeader(X_FORWARDED_PROTO).indexOf("https") != 0) {
response.sendRedirect("https://" + request.getServerName() + request.getPathInfo());
return;
}
}
filterChain.doFilter(request, response);
}
@Override
public void destroy() {
// nothing
}
}
Works like a charm.