Java Web 应用中,如果没有对 JESSIONID 这类 Cookie 信息设置 httpOnly 属性,就存中这种风险:
可以通过 js 的 document.cookie 打印会话信息,并窃取或操纵客户会话和 cookie,它们可能用于模仿合法用户,从而使黑客能够以该用户身份查 看或变更用户记录以及执行事务。
此外,会话 ID 应该在登陆成功后重置,迫使客户端得到一个新的会话 ID,这两项是会话相关的安全内容。本文将整理重置会话的方法和不同服务器对 httpOnly
属性支持的情况。
会话标识更新操作,是指在用户登录成功后,将旧的 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; } 复制代码
Tomcat 下,request 的 Cookie 数量只有一个 JSESSIONID ,但是 Jboss 下有两个,为什么呢?
Tomcat 默认是开启了 httpOnly 的,它在 context.xml 配置中是通过
Context useHttpOnly="true" 复制代码
属性控制的,默认是 true 开启的,所以我们在一个 web 应用中,抓包的响应头域会自动带着这个属性。
使用 js 获取 cookie 是空的,
部署在 jboss 服务器上的应用,它的会话是可以通过 js 获取到的:
所以为了兼容所有服务器,保守的措施是,在登陆成功后,对 Response 的 Header 中关于会话的信息单独添加 httpOnly 属性:
response.setHeader("Set-Cookie",httpResponse.getHeader("Set-Cookie")+";HttpOnly"); 复制代码
从这个 httpOlny 属性来看, Tomcat 的安全配置比 Jboss 要好呢。因为本地一直用 Tomcat 部署,所以总是无法复现这个问题,后来对比想了一下可能是部署服务器不同,继续验证果然在此。