背景
Java Web 应用中,如果没有对 JESSIONID 这类 Cookie 信息设置 httpOnly 属性,就存中这种风险:
可以通过 js 的 document.cookie 打印会话信息,并窃取或操纵客户会话和 cookie,它们可能用于模仿合法用户,从而使黑客能够以该用户身份查 看或变更用户记录以及执行事务。
此外,会话 ID 应该在登陆成功后重置,迫使客户端得到一个新的会话 ID,这两项是会话相关的安全内容。本文将整理重置会话的方法和不同服务器对 httpOnly
属性支持的情况。
登陆成功后重置 httpSession
会话标识更新操作,是指在用户登录成功后,将旧的 Request 信息获取到一个临时对象中,然后调用会话对象的 invalidate
方法,再重新回写到新的会话对象,常规代码如下:
/**
* 重置sessionid,原session中的数据自动转存到新session中
* @param request
*/
private HttpSession renewSessionId(HttpServletRequest request){
HttpSession session = request.getSession(false);
//首先将原session中的数据转移至一临时map中
Map<String,Object> tempMap = new HashMap<String,Object>();
Enumeration<String> sessionNames = session.getAttributeNames();
while(sessionNames.hasMoreElements()){
String sessionName = sessionNames.nextElement();
tempMap.put(sessionName, session.getAttribute(sessionName));
}
//注销原session,为的是重置sessionId
session.invalidate();
//将临时map中的数据转移至新session
session = request.getSession(true);
logger.info("after session id: " + session.getId());
for(Map.Entry<String, Object> entry : tempMap.entrySet()){
session.setAttribute(entry.getKey(), entry.getValue());
}
return session;
}
复制代码
httpOnly 属性
Tomcat 下,request 的 Cookie 数量只有一个 JSESSIONID ,但是 Jboss 下有两个,为什么呢?
Tomcat 和 Jboss 的 httpOnly 配置
Tomcat 默认是开启了 httpOnly 的,它在 context.xml 配置中是通过
Context useHttpOnly="true"
复制代码
属性控制的,默认是 true 开启的,所以我们在一个 web 应用中,抓包的响应头域会自动带着这个属性。
使用 js 获取 cookie 是空的,Jboss 的 httpOnly
部署在 jboss 服务器上的应用,它的会话是可以通过 js 获取到的:
所以为了兼容所有服务器,保守的措施是,在登陆成功后,对 Response 的 Header 中关于会话的信息单独添加 httpOnly 属性:response.setHeader("Set-Cookie",httpResponse.getHeader("Set-Cookie")+";HttpOnly");
复制代码
编程启示录
从这个 httpOlny 属性来看, Tomcat 的安全配置比 Jboss 要好呢。因为本地一直用 Tomcat 部署,所以总是无法复现这个问题,后来对比想了一下可能是部署服务器不同,继续验证果然在此。