为什么https被redirect成了http?

本文探讨了全站HTTPS的实现细节,特别是SSL卸载的概念和技术。通过将SSL配置在负载均衡器上,并处理握手后将解密的HTTPS数据转发给后台Web服务器,实现了内网非加密HTTP传输。文章还介绍了如何确保重定向始终保持HTTPS状态的方法。
全站HTTPS并不是配置证书CA,改改路径URL那么简单!

SSL卸载(SSL Offloading):把SSL配置在负载均衡器上,然后通过其处理握手之后将decode的https数据转发给后台的Web服务器。
如下构成:

|
|(https)
|
Load Balancer
/ | \
/ | \
/(http) |(http) \(http)
WebServer1 WebServer2 WebServer3

HTTPS的加密传输将只限于客户端发起请求到负载均衡器之间的公网阶段,内网的通讯仍然使用非加密的HTTP传输。每个Web服务器中所有的处理请求都认为是来自http,[b]所有相对路径的 sendredirect 将都会被转发到http![/b]

比如在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);
}

}


如果采用Spring的话可以设置:redirectHttp10Compatible=false。
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
<property name="redirectHttp10Compatible" value="false" />
</bean>


参考:
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
### HTTP 307 Temporary Redirect 状态码的含义 HTTP 307 Temporary Redirect 是一种用于指示客户端临时重定向到另一个 URL 的状态码。与传统的 301 或 302 状态码不同,307 明确要求客户端在重定向请求时保持原始请求方法(如 POST)不变,除非用户明确确认更改 [^1]。 #### 1. 307 与其他重定向状态码的区别 - **301 Moved Permanently** 和 **302 Found**:这两个状态码通常表示资源已被永久或临时移动,但浏览器在处理非 GET 或 HEAD 请求时可能不会自动重定向,或者会将 POST 请求转换为 GET 请求 。 - **303 See Other**:该状态码明确指示客户端应使用 GET 方法重新请求新的 URL,即使原始请求是 POST 或其他方法 [^2]。 - **307 Temporary Redirect**:与 303 不同,307 要求客户端必须保持原始请求方法不变,并且仅在临时重定向的情况下使用 [^2]。 #### 2. 307 的典型应用场景 307 常用于需要保留原始请求方法和请求体的场景,例如: - 在进行表单提交后,服务器希望将请求临时重定向到另一个地址,同时确保客户端继续使用 POST 方法发送数据 [^2]。 - 避免因浏览器自动将 POST 请求转换为 GET 请求而导致的数据丢失问题 [^1]。 #### 3. 如何处理 307 Temporary Redirect 当客户端接收到 307 状态码时,它应该检查响应头中的 `Location` 字段,并根据该字段提供的 URL 发起新的请求。在此过程中,客户端应保持原始请求方法不变 [^2]。 ##### 示例代码 以下是一个简单的 Java Servlet 示例,展示如何返回 307 状态码并设置重定向 URL: ```java import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class Http307TestServlet extends HttpServlet { private static final long serialVersionUID = 7047368191379656914L; static final String tempRedirectUrl = "http://www.baidu.com"; @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { resp.setStatus(307); resp.setHeader("Location", tempRedirectUrl); PrintWriter p = resp.getWriter(); p.println("Location:" + tempRedirectUrl); p.println("Note: this is 307 redirect Url."); p.close(); } } ``` #### 4. 307 的潜在问题及解决方法 - **问题 1:客户端不支持 307** - 某些旧版本的浏览器或客户端可能无法正确处理 307 状态码,导致请求失败。 - **解决方法**:建议在服务器端提供兼容性处理逻辑,例如回退到 302 并附加提示信息,确保客户端能够正常处理重定向。 - **问题 2:POST 请求被错误转换为 GET 请求** - 即使服务器返回 307 状态码,某些代理或中间件可能会错误地将 POST 请求转换为 GET 请求。 - **解决方法**:确保服务器和中间件配置正确,并严格遵循 HTTP/1.1 规范 [^2]。 - **问题 3:安全性和数据泄露风险** - 如果重定向的目标 URL 包含敏感信息,可能会导致数据泄露。 - **解决方法**:避免在 `Location` 头中包含敏感信息,并使用 HTTPS 加密通信以保护数据安全 [^2]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值