Issue
I am using Spring-Boot running in an AWS instance with an Elastic Load Balancer. I am using Spring MVC with login security with the server port is set to 8080. I have installed an AWS generated certificate with the correct web name, test.mydomain.com, in the ELB. The ELB listeners are set up for port 80 HTTP >> 8080 HTTP and 443 HTTPS >> 8080 HTTP. Here is my WebSecurityConfig class,
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
UserDetailsService userDS;
@Override
protected void configure(HttpSecurity http) throws Exception{
// Allows access for .css, .js, and .images files
http.authorizeRequests()
.antMatchers("/resources/**")
.permitAll()
.anyRequest()
.permitAll();
// Access management for all other requests
http.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/home")
.invalidateHttpSession(true)
.permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDS).passwordEncoder(passwordEncoder());
}
@Override
protected UserDetailsService userDetailsService() {
return userDS;
}
@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
}
When I access the home page, https://test.mydomian.com/home, everything is fine and the page is secure. I am certain the certificate is working. I tried using curl -vk https:test.mydomain.com/home and verified that the certificate is working. When I click login, the page reverts to HTTP (Unsecure) and all other pages going forward are HTTP.
I tried the following experiment with the ELB. I eliminated the port 80 listener so that I only had a one listener on 443 -- 443 HTTPS >> HTTP 8080. Again, I logged in to https://test.mydomain.com/home and the page was secure. When I clicked login, the browser failed to find the page. I noticed the browser address bar had http://test.mydomain.com/login. Since there was no listener for port 80 the request failed. Why is my login page trying to access port 80? In my application.properties page I have have server.port = 8080. It makes no sense to me that the login page is reverting to port 80. Anyone have any ideas? I have seen a lot of posts talking about login ELB redirects causing a lot of Spring MVC ELB problems. Could this be my problem?
Solution
As your ELB will act as a proxy you'll have to configure Spring (and the server you're running on) to use the forward headers by setting server.use-forward-headers
to true
in your application.properties
. See https://docs.spring.io/spring-boot/docs/1.5.21.RELEASE/reference/html/howto-embedded-servlet-containers.html#howto-use-tomcat-behind-a-proxy-server for more information.
Edit: As of Spring Boot 2.2 the server.use-forward-headers
property has been deprecated in favor for server.forward-headers-strategy
. See https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.2-Release-Notes#deprecations-in-spring-boot-22
Answered By - JTP
Answer Checked By - Senaida (JavaFixing Volunteer)