SSL卸载(SSL Offloading):把SSL配置在负载均衡器上,然后通过其处理握手之后将decode的https数据转发给后台的Web服务器。
如下构成:
|
|(https)
|
Load Balancer
/ | \
/ | \
/(http) |(http) \(http)
WebServer1 WebServer2 WebServer3
HTTPS的加密传输将只限于客户端发起请求到负载均衡器之间的公网阶段,内网的通讯仍然使用非加密的HTTP传输。每个Web服务器中所有的处理请求都认为是来自http, 所有相对路径的 sendredirect 将都会被转发到http!
比如在Filter或Interceptor里的sendRedirect:
response.sendRedirect(request.getContextPath() + "/admin/welcome.do?flag=timeout");
或者Spring的Controller里的“redirect:”:
return "redirect:/admin/welcome.do";
通过HttpServletResponseWrapper可以通过Filter拦截SendRedirect请求并固定跳转到HTTPS。
web.xml
AbsoluteSendRedirectFilter com.rensanning.core.filter.AbsoluteSendRedirectFilter AbsoluteSendRedirectFilter /*
AbsoluteSendRedirectFilter.java
public class AbsoluteSendRedirectFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { RedirectResponseWrapper redirectResponseWrapper = new RedirectResponseWrapper(request, response); filterChain.doFilter(request, redirectResponseWrapper); } }
RedirectResponseWrapper.java
public class RedirectResponseWrapper extends HttpServletResponseWrapper { private final HttpServletRequest request; public RedirectResponseWrapper(final HttpServletRequest inRequest, final HttpServletResponse response) { super(response); this.request = inRequest; } @Override public void sendRedirect(final String pLocation) throws IOException { if (StringUtils.isBlank(pLocation)) { super.sendRedirect(pLocation); return; } try { final URI uri = new URI(pLocation); if (uri.getScheme() != null) { super.sendRedirect(pLocation); return; } } catch (URISyntaxException ex) { super.sendRedirect(pLocation); } // !!! FIX Scheme !!! String finalurl = "https://" + this.request.getServerName(); if (request.getServerPort() != 80 && request.getServerPort() != 443) { finalurl += ":" + request.getServerPort(); } finalurl += pLocation; super.sendRedirect(finalurl); } }
如果采用Spring的话可以设置:redirectHttp10Compatible=false。
参考:
http://www.exampit.com/blog/javahunter/5-8-2016-Why-does-https-become-http-on-a-sendredirect
http://stackoverflow.com/questions/3401113/spring-mvc-redirect-prefix-always-redirects-to-http-how-do-i-make-it-stay