Https跳到http时session信息丢失的分析及解决方案
2008-01-20 22:10
501 查看
我们在YMU(website monitoring)项目开发过程中发现一个关于登录功能的奇怪的问题。
当按一般流程使用登录功能时是没问题的,即:点击官网 (http://YouMonitor.Us)的login链接,然后跳转到https://YouMonitor.Us/login.shtml,输入正确的用户名和密码后,则能正确转入功能页面(http协议)。
而如果跳过第一步,直接在浏览器中输https://YouMonitor.Us/login.shtml,则不能正确转入功能页面。
在第二种方式下,用户名被保存在https下创建的session中,而不能被传递到http协议,这样当以http协议跳转到功能页面时,发现session中没有用户名,系统就会认为没有登录,就出问题了。
再深入分析session的传递机制,其中一种方式是通过JSESSIONID这个cookie在浏览器和web server之间进行传递的。而为了增强安全性,从tomcat 4.0开始,在https协议下生成的cookie不会被传递到http协议。
这就是登录问题产生的根本原因。
还没有更方便的方法呢?上周公司一同事在网上又 找到一个更加简洁和方面的方法。其主要思路是建立一个filter, 对所有的Servlet Request做处理,如果session是新的https session,则创建一个JSESSIONID cookie,并设置到Servlet Response中,这样就突破了tomcat的限制,把https下的session传递到http协议下。
根据文章说明试了一下,果然成功了!这下解决了系统的一个BUG,不错啊!
private HttpServletResponse response = null;
public MyRequestWrapper(HttpServletRequest request) {
super(request);
}
public void setResponse(HttpServletResponse response) { this.response = response;}
public HttpSession getSession(){
HttpSession session = super.getSession();
processSessionCookie(session);
return session;
}
public HttpSession getSession(boolean create){
HttpSession session = super.getSession(create);
processSessionCookie(session);
return session;
}
private void processSessionCookie(HttpSession session){
if (null == response || null == session) {
// No response or session object attached, skip the pre processing
return;
}
// cookieOverWritten - 用于过滤多个Set-Cookie头的标志
Object cookieOverWritten = getAttribute("COOKIE_OVERWRITTEN_FLAG");
if (null == cookieOverWritten && isSecure() && isRequestedSessionIdFromCookie() && session.isNew()) {
// 当是https协议,且新session时,创建JSESSIONID cookie以欺骗浏览器
Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(-1); // 有效时间为浏览器打开或超时
String contextPath = getContextPath();
if ((contextPath != null) && (contextPath.length() > 0)) {
cookie.setPath(contextPath);
}
else {
cookie.setPath("/");
}
response.addCookie(cookie); // 增加一个Set-Cookie头到response
setAttribute("COOKIE_OVERWRITTEN_FLAG", "true");// 过滤多个Set-Cookie头的标志
}
}
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
MyRequestWrapper myrequest = new MyRequestWrapper(request);
myrequest.setResponse(response);
chain.doFilter(myrequest, response);
}
}
当按一般流程使用登录功能时是没问题的,即:点击官网 (http://YouMonitor.Us)的login链接,然后跳转到https://YouMonitor.Us/login.shtml,输入正确的用户名和密码后,则能正确转入功能页面(http协议)。
而如果跳过第一步,直接在浏览器中输https://YouMonitor.Us/login.shtml,则不能正确转入功能页面。
原因分析
经调试发现是由于session造成的。当用户名和密码通过验证后,YMU会在session中保存登录用户名。在第二种方式下,用户名被保存在https下创建的session中,而不能被传递到http协议,这样当以http协议跳转到功能页面时,发现session中没有用户名,系统就会认为没有登录,就出问题了。
再深入分析session的传递机制,其中一种方式是通过JSESSIONID这个cookie在浏览器和web server之间进行传递的。而为了增强安全性,从tomcat 4.0开始,在https协议下生成的cookie不会被传递到http协议。
这就是登录问题产生的根本原因。
解决方案
前一段时间在网上找到一种解决方法,该方法修改tomcat的源代码,以解除cookie传递的限制。该方法的缺点是每次tomcat升级都要重新修改并编译,很不方便。还没有更方便的方法呢?上周公司一同事在网上又 找到一个更加简洁和方面的方法。其主要思路是建立一个filter, 对所有的Servlet Request做处理,如果session是新的https session,则创建一个JSESSIONID cookie,并设置到Servlet Response中,这样就突破了tomcat的限制,把https下的session传递到http协议下。
根据文章说明试了一下,果然成功了!这下解决了系统的一个BUG,不错啊!
附:源代码
1. 先建立Wrapper类,用于处理所有的Serverlet Request:
public class MyRequestWrapper extends HttpServletRequestWrapper{private HttpServletResponse response = null;
public MyRequestWrapper(HttpServletRequest request) {
super(request);
}
public void setResponse(HttpServletResponse response) { this.response = response;}
public HttpSession getSession(){
HttpSession session = super.getSession();
processSessionCookie(session);
return session;
}
public HttpSession getSession(boolean create){
HttpSession session = super.getSession(create);
processSessionCookie(session);
return session;
}
private void processSessionCookie(HttpSession session){
if (null == response || null == session) {
// No response or session object attached, skip the pre processing
return;
}
// cookieOverWritten - 用于过滤多个Set-Cookie头的标志
Object cookieOverWritten = getAttribute("COOKIE_OVERWRITTEN_FLAG");
if (null == cookieOverWritten && isSecure() && isRequestedSessionIdFromCookie() && session.isNew()) {
// 当是https协议,且新session时,创建JSESSIONID cookie以欺骗浏览器
Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(-1); // 有效时间为浏览器打开或超时
String contextPath = getContextPath();
if ((contextPath != null) && (contextPath.length() > 0)) {
cookie.setPath(contextPath);
}
else {
cookie.setPath("/");
}
response.addCookie(cookie); // 增加一个Set-Cookie头到response
setAttribute("COOKIE_OVERWRITTEN_FLAG", "true");// 过滤多个Set-Cookie头的标志
}
}
}
2. 再把上述Wrapper类与Filter建立关联:
public final class TestFilter implements Filter{public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
MyRequestWrapper myrequest = new MyRequestWrapper(request);
myrequest.setResponse(response);
chain.doFilter(myrequest, response);
}
}
相关文章推荐
- Https跳到http时session信息丢失的分析及解决方案
- http https session丢失
- iOS开发工具-如何使用网络封包分析工具Charles,通过配置proxy对http、https、tcp、udp 等协议的请求响应过程交互信息进行分析、判断、解决我们移动开发中的遇到的各种实际问题。
- IIS安全工具UrlScan介绍 ASP.NET 两种超强SQL 注入免费解决方案( 基于IIS,使用免费工具) 批改或隐藏IIS7.5的Server头信息 移除X-Powered-By,MVC,ASP.NET_SessionId 的 HTTP头或者cookie名称
- http https session丢失
- CakePHP: HTTPS HTTP页面跳转导致登录信息丢失
- 在https和http间切换时session丢失问题
- windows2003中IIS6的session以及application在iframe中丢失问题的解决方案
- https页面与Http页面自动切换-SSL解决方案
- asp.net 删除目录session丢失解决方案
- Session丢失原因与解决方案小结 (zt)
- HTTP & HTTPS, Session & Cookie 知识点总结
- feign调用session丢失解决方案
- PhantomJSDriver能访问http却不能访问https的解决方案
- HttpClient4.3.x请求https的解决方案
- feign调用session丢失解决方案
- 自理解Https原理:证书传递,握手信息传递,数据加密解密的分析。
- JQuery文件上传插件uploadify在MVC中Session丢失的解决方案
- Beforeunload打点丢失原因分析及解决方案
- ASP.NET Session丢失问题原因及解决方案[转]