如何在Heroku上强制使用HTTPS进行Spring Boot应用程序?

时间:2017-10-26 14:22:53

标签: ssl spring-boot heroku https

我尝试使用FORCE_HTTPS=trueSECURITY_REQUIRE_SSL=true作为配置变量,但都不起作用。我知道前者是由Cloud Foundry支持的,但是我已经向Heroku确认他们不支持它。 Spring Boot支持SECURITY_REQUIRE_SSL属性,但可能仅适用于基本身份验证?

3 个答案:

答案 0 :(得分:9)

我可以通过创建HttpEnforcer过滤器来解决此问题:

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

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) {
                String pathInfo = (request.getPathInfo() != null) ? request.getPathInfo() : "";
                response.sendRedirect("https://" + request.getServerName() + pathInfo);
                return;
            }
        }

        filterChain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        // nothing
    }
}

并在现有的@Configuration课程中注册。

@Bean
public Filter httpsEnforcerFilter(){
    return new HttpsEnforcer();
}

这与我在上面的评论中发布的解决方案不同,因为对pathInfo进行了空检查。没有它,它仍然有效,但Location最终会显示null

$ curl -i http://www.21-points.com
HTTP/1.1 302 Found
Server: Cowboy
Connection: keep-alive
Expires: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
X-Xss-Protection: 1; mode=block
Pragma: no-cache
Location: https://www.21-points.comnull
Date: Tue, 31 Oct 2017 14:33:26 GMT
X-Content-Type-Options: nosniff
Content-Length: 0
Via: 1.1 vegur

答案 1 :(得分:3)

根据the docs on heroku,这应该是你所需要的:

@Configuration
public class WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.requiresChannel()
      .requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null)
      .requiresSecure();
  }
}
  

强制使用HTTPS

     

除非您有非常具体的需求,否则您的应用应该针对所有请求使用HTTPS。 Heroku为每个应用程序提供HTTPS URL(格式为https://.herokuapp.com),以及用于添加自己的域和证书的免费工具。

     

通过在Spring Boot应用程序中添加以下配置,可以在Heroku上运行应用程序时强制使用HTTPS。

答案 2 :(得分:1)

如果您使用的是Spring引导,则必须为项目添加依赖性

for maven

<dependency>
  <groupId>io.github.createam-labs</groupId>
  <artifactId>spring-boot-starter-heroku</artifactId>
  <version>1.1</version>
</dependency>

或gradle

compile('io.github.createam-labs:spring-boot-starter-heroku:1.1')

然后通过添加以下行

application.properties文件中启用https强制执行
heroku.enforceHttps=true

有关详细信息,您可以访问我的项目网站 https://github.com/createam-labs/spring-boot-starter-heroku