背景
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 部署,所以總是無法復現這個問題,後來對比想了一下可能是部署服務器不同,繼續驗證果然在此。