如何在 tomcat / java webapps 中配置 HttpOnly cookie?
题
阅读 Jeff 的博客文章后 保护您的 Cookie:仅HTTP. 。我想在我的 Web 应用程序中实现 HttpOnly cookie。
如何告诉 tomcat 在会话中使用仅 http 的 cookie?
其他提示
更新:这里的JSessionId东西仅适用于较旧的容器。请使用JT当前接受的答案,除非您使用<tomcat 6.0.19或<tomcat 5.5.5.28或其他不支持HTTPonly JSessionId cookie作为配置选项的容器。
在您的应用程序中设置 cookie 时,请使用
response.setHeader( "Set-Cookie", "name=value; HttpOnly");
然而,在许多Web应用程序中,最重要的cookie是会话标识符,它由容器自动设置为JSESSIONID cookie。
如果只使用这个cookie,可以写一个ServletFilter在出去的时候重新设置cookie,强制JSESSIONID为HttpOnly。页面位于 http://keepitlocked.net/archive/2007/11/05/java-and-httponly.aspx http://alexsmolen.com/blog/?p=16 建议在过滤器中添加以下内容。
if (response.containsHeader( "SET-COOKIE" )) {
String sessionid = request.getSession().getId();
response.setHeader( "SET-COOKIE", "JSESSIONID=" + sessionid
+ ";Path=/<whatever>; Secure; HttpOnly" );
}
但请注意,这将覆盖所有 cookie,并且仅设置您在此过滤器中指定的内容。
如果您对 JSESSIONID cookie 使用其他 cookie,则需要扩展此代码以设置过滤器中的所有 cookie。对于多个 cookie,这不是一个很好的解决方案,但对于仅 JSESSIONID 设置来说,这可能是一个可接受的快速修复。
请注意,随着您的代码随着时间的推移而发展,当您忘记此过滤器并尝试在代码中的其他位置设置另一个 cookie 时,就会有一个令人讨厌的隐藏错误在等着您。当然,它不会被设置。
但这确实是一个黑客行为。如果您确实使用 Tomcat 并且可以编译它,那么请看看 Shabaz 的出色建议,将 HttpOnly 支持修补到 Tomcat 中。
请小心不要覆盖 https 会话中的“;secure”cookie 标志。该标志可防止浏览器通过未加密的 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 参数的支持. 。目前可以找到一个有点复杂的解决方法 这里, ,这基本上可以归结为手动修补 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);
}
如果您的Web服务器支持Serlvet 3.0规范,例如tomcat 7.0+,您可以在下面使用 web.xml
作为:
<session-config>
<cookie-config>
<http-only>true</http-only>
<secure>true</secure>
</cookie-config>
</session-config>
正如文档中提到的:
仅HTTP: :指定该Web应用程序创建的任何会话跟踪cookie是否将被标记为httponly
安全的: :指定该Web应用程序创建的任何会话跟踪cookie是否将被标记为安全
还应该注意的是,打开 HttpOnly 会破坏需要有状态访问回 jvm 的小程序。
Applet http 请求不会使用 jsessionid cookie,并且可能会被分配给不同的 tomcat。
在 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();
}
}
}
我发现于 OWASP
<session-config>
<cookie-config>
<http-only>true</http-only>
</cookie-config>
</session-config>
这也修复了“配置中的 httponlycookies”安全问题