3

我发现了很多关于在 heroku 下强制执行 HTTPS 的问题,但没有关于 java.util 的回应。

这是我找到的链接:

斯卡拉:http ://www.andersen-gott.com/2012/03/using-unfiltered-and-https-on-heroku.html

Rails:Rails - 如何从 http://example.com 重定向到 https://www.example.com

请注意,我使用的是 Spring MVC 3.1,所以我更喜欢基于 WebMvcConfigurerAdapter.addInterceptors(InterceptorRegistry registry) 的解决方案

4

4 回答 4

6

这是一个将所有非 https 请求重定向到 https 的 Servlet 过滤器:

package com.jamesward;

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

        filterChain.doFilter(request, response);
    }

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

我将其作为 Servlet 过滤器执行,因为我无法让 Spring Interceptor 拦截静态资产(资源)请求。

完整来源:https ://github.com/jamesward/springmvc-https-enforcer

于 2012-08-10T23:09:40.363 回答
2

较晚的答案,但另一种配置驱动的方法是requires-channel="https"在各种<sec:intercept-url>标签上使用 Spring Security with ,并与 Tomcat 结合使用RemoteIpValve,后者处理先前答案中提到的相同代理标头(x-forwarded-proto等)。Valve 会根据代理标头更改行为HttpServletRequest.isSecure()以反映代理报告的协议,而不是连接器实际接收的协议 - 因此,任何依赖于isSecure()做正确事情的框架(如 Spring)在 SSL 卸载时都会正常运行。

Heroku 中的 SSL 重定向有关于配置 Valve 以与 webapp-runner 和 Heroku 一起使用的说明。

此外,我建议使用PropertyPlaceholderConfigurer让值可以被环境覆盖。例如,在您的 Spring Security 配置中:

<sec:intercept-url pattern="/api/**" requires-channel="${REQUIRES_CHANNEL}" access="..."/>

相关内容application-config.xml将包括以下内容:

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
  <property name="properties" ref="applicationProperties"/>
</bean>

<bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  <property name="locations">
    <list>
      <value>classpath:/application-config.properties</value>
    </list>
  </property>
</bean>

application-config.properties文件将REQUIRES_CHANNEL=http默认包含,然后在部署到 Heroku 时,您设置heroku config:set REQUIRES_CHANNEL=https为覆盖。

于 2012-11-30T19:43:02.380 回答
0

詹姆斯过滤器的一点优化版本

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

public class HttpsFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpReq = (HttpServletRequest) request;
        HttpServletResponse httpResp = (HttpServletResponse) response;
        if ("http".equalsIgnoreCase(httpReq.getHeader("x-forwarded-proto"))) {
            StringBuffer requestURL = httpReq.getRequestURL();
            httpResp.sendRedirect("https" + requestURL.substring(requestURL.indexOf(":")));
        } else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {
    }
}

要旨

于 2017-01-24T23:12:15.440 回答
-1

这是基于 spring mvc 的 hte 解决方案:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class ForceHerokuSsl extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         String proto = request.getHeader("x-forwarded-proto");
         return proto == null || "https".equalsIgnoreCase(proto);
    }
}

然后在配置中:

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {

   public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new ForceHerokuSslInterceptor());
   }
}
于 2014-02-26T21:33:21.427 回答