一.场景:
在企业内网应用,以及一些安全要求不高的网站会有一些https转http的需求,例如只是登陆https协议,其他请求都是走http协议,走http协议不再需要重新登陆一次。
二.解决方案
Cookie时效:
- 当cookie是secure的情况下,当服务器从https协议重定向到http协议后,这样的cookie就不会随请求发送到服务器。
- 当cookie不是secure的情况下,当服务器从http协议重定向到https协议后,这样的cookie就不会随请求发送到服务器。
所以解决的方法就是在https认证后,除了构造一个secure的cookie(包含session id信息),同时构造一个非secure的cookie(包含session id信息),这样页面跳转后就一致保持session有效了,从而达到https重定向到http后不需要登陆的效果。
图中没有详细描述web容器的跳转,仅仅想描述协议转换的实现过程。
主要点说明:
重定向跳转在页面中实现,而不在Authenticator实现,也不在Filter实现,因为Response已经commit。
Filter实现增加非Secure cookie的逻辑,代码:
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class HttpsCookieFilter implements Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { final HttpServletRequest httpRequest = (HttpServletRequest) request; final HttpServletResponse httpResponse = (HttpServletResponse) response; final HttpSession session = httpRequest.getSession(false); // servlet3 if (session != null) { System.out.println("HttpsCookieFilter set session cookie:" + session.getId()); final Cookie cookie = new Cookie("JSESSIONID", session.getId()); cookie.setMaxAge(-1);//no store cookie.setSecure(false); cookie.setPath(httpRequest.getContextPath()); cookie.setHttpOnly(true); httpResponse.addCookie(cookie); } //servlet2 //httpResponse.addHeader( // "Set-Cookie", // "JSESSIONID=" + session.getId() + "; Path=" // + httpRequest.getContextPath() + "; HttpOnly"); chain.doFilter(request, response); } @Override public void init(FilterConfig arg0) throws ServletException { } }
三.其他
在http://www.ruanyifeng.com/blog/2011/02/seven_myths_about_https.html
有提到没有必要从https重定向到http的一些原因。