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
<filter> <filter-name>AbsoluteSendRedirectFilter</filter-name> <filter-class>com.rensanning.core.filter.AbsoluteSendRedirectFilter</filter-class> </filter> <filter-mapping> <filter-name>AbsoluteSendRedirectFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
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); } }