如何在tomcat / java webapps中configurationHttpOnly cookie?
在阅读Jeff的博客文章“ 保护您的Cookie:HttpOnly”之后 。 我想在我的Web应用程序中实现HttpOnly cookie。
你如何告诉tomcat使用仅用于会话的http cookie?
从Tomcat 6.0.19和Tomcat 5.5.28开始支持httpOnly。
查看错误44382的更新日志条目。
错误44382的最后一条评论指出,“这已经应用到5.5.x ,并且将包含在5.5.28之后”。 不过,5.5.28似乎并没有公布。
可以为conf / context.xml中的所有webapps启用httpOnlyfunction:
<Context useHttpOnly="true"> ... </Context>
我的解释是,它也可以通过在conf / server.xml中设置所需的上下文条目(与上面相同的方式)在个别上下文中工作。
更新:这里的JSESSIONID的东西只适用于旧的容器。 除非使用<Tomcat 6.0.19或<Tomcat 5.5.28或另一个不支持HttpOnly JSESSIONID cookie的容器作为configuration选项,否则请使用jt当前接受的答案。
在您的应用中设置Cookie时,请使用
response.setHeader( "Set-Cookie", "name=value; HttpOnly");
但是,在许多web应用程序中,最重要的cookie是会话标识符,它由容器自动设置为JSESSIONID cookie。
如果你只使用这个cookie,你可以编写一个ServletFilter来重新设置cookies,强制JSESSIONID到HttpOnly。 http://keepitlocked.net/archive/2007/11/05/java-and-httponly.aspx http://alexsmolen.com/blog/?p=16的页面build议在filter中添加以下内容。;
if (response.containsHeader( "SET-COOKIE" )) { String sessionid = request.getSession().getId(); response.setHeader( "SET-COOKIE", "JSESSIONID=" + sessionid + ";Path=/<whatever>; Secure; HttpOnly" ); }
但是请注意,这将覆盖所有Cookie,并只设置您在此filter中的状态。
如果您对JSESSIONID Cookie使用其他Cookie,则需要扩展此代码以在filter中设置所有Cookie。 对于多个cookie,这不是一个很好的解决scheme,但对于仅用于JSESSIONID的安装程序来说,这可能是一个可以接受的快速解决scheme。
请注意,随着时间的推移,随着代码的不断发展,当你忘记这个filter,并尝试在你的代码的其他地方设置另一个cookie时,会有一个令人讨厌的隐藏的bug等着你。 当然,它不会被设置。
这真的是一个黑客。 如果你使用Tomcat并且可以编译它,那么看看Shabaz的优秀build议,将HttpOnly支持修补到Tomcat中。
请注意不要在https会话中覆盖“; secure”cookie标志。 这个标志防止浏览器通过未encryption的http连接发送cookie,基本上使得https对合法请求的使用毫无意义。
private void rewriteCookieToHeader(HttpServletRequest request, HttpServletResponse response) { if (response.containsHeader("SET-COOKIE")) { String sessionid = request.getSession().getId(); String contextPath = request.getContextPath(); String secure = ""; if (request.isSecure()) { secure = "; Secure"; } response.setHeader("SET-COOKIE", "JSESSIONID=" + sessionid + "; Path=" + contextPath + "; HttpOnly" + secure); } }
对于会话cookie,它似乎还不支持在Tomcat中。 查看错误报告需要添加对HTTPOnly会话cookie参数的支持 。 现在可以find一个有点涉及的解决方法,基本上归结为手动修补Tomcat。 在这一刻,我真的找不到一个简单的方法来做到这一点,我很害怕。
要总结变通方法,需要下载5.5 源代码 ,然后在以下位置更改源代码:
org.apache.catalina.connector.Request.java
//this is what needs to be changed //response.addCookieInternal(cookie); //this is whats new response.addCookieInternal(cookie, true); }
org.apache.catalina.connectorResponse.addCookieInternal
public void addCookieInternal(final Cookie cookie) { addCookieInternal(cookie, false); } public void addCookieInternal(final Cookie cookie, boolean HTTPOnly) { if (isCommitted()) return; final StringBuffer sb = new StringBuffer(); //web application code can receive a IllegalArgumentException //from the appendCookieValue invokation if (SecurityUtil.isPackageProtectionEnabled()) { AccessController.doPrivileged(new PrivilegedAction() { public Object run(){ ServerCookie.appendCookieValue (sb, cookie.getVersion(), cookie.getName(), cookie.getValue(), cookie.getPath(), cookie.getDomain(), cookie.getComment(), cookie.getMaxAge(), cookie.getSecure()); return null; } }); } else { ServerCookie.appendCookieValue (sb, cookie.getVersion(), cookie.getName(), cookie.getValue(), cookie.getPath(), cookie.getDomain(), cookie.getComment(), cookie.getMaxAge(), cookie.getSecure()); } //of course, we really need to modify ServerCookie //but this is the general idea if (HTTPOnly) { sb.append("; HttpOnly"); } //if we reached here, no exception, cookie is valid // the header name is Set-Cookie for both "old" and v.1 ( RFC2109 ) // RFC2965 is not supported by browsers and the Servlet spec // asks for 2109. addHeader("Set-Cookie", sb.toString()); cookies.add(cookie); }
如果你的Serlvet 3.0 web服务器,像tomcat 7.0+,你可以在web.xml
使用如下:
<session-config> <cookie-config> <http-only>true</http-only> <secure>true</secure> </cookie-config> </session-config>
正如文档中提到的那样:
HttpOnly :指定此Web应用程序创build的任何会话跟踪cookie是否将被标记为HttpOnly
Secure(安全) :指定由此Web应用程序创build的任何会话跟踪Cookie将被标记为安全,即使启动相应会话的请求使用纯HTTP而不是HTTPS
请参考如何设置java web appliaction的httponly和session cookie
还应该注意的是,打开HttpOnly会打破需要有状态访问的小程序回到jvm。
Applet http请求将不会使用jsessionid cookie,并可能被分配给不同的tomcat。
对于我明确设定的cookie,我转而使用Apache Shiro提供的SimpleCookie 。 它不从javax.servlet.http.Cookieinheritance,所以它需要更多的杂耍让一切正常工作,但它确实提供了一个属性集HttpOnly,它与Servlet 2.5的工作。
为了在响应中设置一个cookie,而不是做response.addCookie(cookie)
你需要做cookie.saveTo(request, response)
。
在Tomcat6中,您可以从HTTP侦听器类有条件地启用:
public void contextInitialized(ServletContextEvent event) { if (Boolean.getBoolean("HTTP_ONLY_SESSION")) HttpOnlyConfig.enable(event); }
使用这个类
import java.lang.reflect.Field; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import org.apache.catalina.core.StandardContext; public class HttpOnlyConfig { public static void enable(ServletContextEvent event) { ServletContext servletContext = event.getServletContext(); Field f; try { // WARNING TOMCAT6 SPECIFIC!! f = servletContext.getClass().getDeclaredField("context"); f.setAccessible(true); org.apache.catalina.core.ApplicationContext ac = (org.apache.catalina.core.ApplicationContext) f.get(servletContext); f = ac.getClass().getDeclaredField("context"); f.setAccessible(true); org.apache.catalina.core.StandardContext sc = (StandardContext) f.get(ac); sc.setUseHttpOnly(true); } catch (Exception e) { System.err.print("HttpOnlyConfig cant enable"); e.printStackTrace(); } } }