Configuring a spring application to use https behind an ELB

I have a couple of sites that run on AWS and take advantage of Elastic Load Balancers to handle proxying to servers in a private VPC as well handling https security. While CloudFront distributions can be configured to upgrade requests to https if they come in as HTTP, I haven’t found a way to configure ELB connections to do the same. What I wanted is for the ELB to listen on both port 80 and 443 and if a connection comes in on 80, then to redirect to the same request on 443. This way if a user just enters the URL into their browser, they’ll automatically be upgraded to https even if they didn’t remember to specify it.

It’s fairly simple to accomplish this with an Interceptor. Create a class that will handle the redirects.

 

@Component
public class SecurityInterceptor extends HandlerInterceptorAdapter {
  
  private static Logger logger = LoggerFactory.getLogger(SecurityInterceptor.class);
  
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    String proto = request.getHeader("X-Forwarded-Proto");
    if (!Strings.isNullOrEmpty(proto)) {
      logger.debug("Found proto: {}", proto);
      if ("http".equalsIgnoreCase(proto)) {
        StringBuffer redirectString = createRedirect(request);
        logger.debug("Redirecting to {}", redirectString);
        response.sendRedirect(redirectString.toString());
        return false;
      }
    }
    logger.debug("No proto header found");
    return true;
  }
  
  private StringBuffer createRedirect(HttpServletRequest request) throws IOException {
    StringBuffer result = request.getRequestURL();
    result.insert(4, "s");
    
    String queryString = request.getQueryString();
    if (!Strings.isNullOrEmpty(queryString)) {
      result.append("?");
      result.append(queryString);
    }
    
    return result;
  }
  
}

Since encryption is handled by the ELB and all traffic arrives at the server as HTTP we have to rely on the x-forwarded headers to know if we should redirect the request back to a secure page.

Then I have a config class to load the Interceptor.

@Configuration
public class WebMVCConfig extends WebMvcConfigurerAdapter {
  
  @Autowired
  private SecurityInterceptor securityInterceptor;

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(securityInterceptor);
  }
}

This Interceptor is specific to the x-forwarded headers that ELBs will send to the backend instance.

 

Spring Boot with JSP and React Template Application

Awhile back I was playing around with moving some personal applications to use spring boot. There are a lot of really nice aspects to this project. You get a whole lot of functionality without having to write boilerplate code.

  1. Executable jar file.
    1. packages entire application as a single executable file.
  2. Service Support
    1. link to your executable jar from /etc/init.d and you get full Linux service support (start, stop, restart, status)
    2. logs go to /var/log/{application name}.log
    3. PID status support in /var/run/
  3. Embedded web container
    1. tomcat or jetty is upgraded with your spring boot version, so you don’t have a separate set of binaries to maintain.

The biggest downside that I could see was that JSPs are not supported out of the box because of a tomcat issue. Spring boot is perfect for developing REST microservices but somewhat limited as a general purpose web application replacement. You need to convert your display code to use Thymeleaf templates, which could be a significant amount of work.

I came across a workaround to get JSPs working as expected. It involved moving files out of the /WEB-INF/ directory and putting them in /resources/META-INF/resources/WEB-INF/. It’s a little weird, but when you do it, everything works as expected. You’re even able to use things like JSP tags just as you would have before.

Another thing that I’ve been spending time thinking about is how to integrate a Java development project with a current Javascript setup. Maven works as well as anything for a large multi-module structure, but how does the Javascript code incorporate? There are a lot of different options. I wanted a build pipeline that would allow you to use the more popular Javascript tools, not break for non-Javascript developers, and allow fast iteration of Javascript changes (doesn’t require a full ‘mvn clean package’ to see changes).

After all of this experimentation, I believe I’ve found a good balance of tools for both Java and Javascript developers. It uses Spring Boot with full JSP support as a base. Gulp and Webpack for the Javascript build pipeline. Has a development mode that uses the Webpack dev server to iterate quickly. It also includes support for development with React, so you can play with the cutting edge of developing web applications.

I’ve done all of the fiddlings with different settings and created a working template application.  Check it out and let me know what you think.