简体   繁体   English

你如何在tomcat / java webapps中配置HttpOnly cookie?

[英]How do you configure HttpOnly cookies in tomcat / java webapps?

After reading Jeff's blog post on Protecting Your Cookies: HttpOnly .阅读 Jeff 关于保护您的 Cookie:HttpOnly的博客文章后。 I'd like to implement HttpOnly cookies in my web application.我想在我的 Web 应用程序中实现 HttpOnly cookie。

How do you tell tomcat to use http only cookies for sessions?你如何告诉 tomcat 在会话中只使用 http cookie?

httpOnly is supported as of Tomcat 6.0.19 and Tomcat 5.5.28.自 Tomcat 6.0.19 和 Tomcat 5.5.28 起支持 httpOnly。

See the changelog entry for bug 44382.请参阅错误 44382 的变更日志条目。

The last comment for bug 44382 states, "this has been applied to 5.5.x and will be included in 5.5.28 onwards."错误44382的最后一条评论指出,“这已应用于5.5.x ,并将包含在 5.5.28 之后。” However, it does not appear that 5.5.28 has been released.但是,似乎没有发布 5.5.28。

The httpOnly functionality can be enabled for all webapps in conf/context.xml :可以为conf/context.xml 中的所有 webapps 启用 httpOnly 功能:

<Context useHttpOnly="true">
...
</Context>

My interpretation is that it also works for an individual context by setting it on the desired Context entry in conf/server.xml (in the same manner as above).我的解释是它也适用于单个上下文,方法是在conf/server.xml 中的所需上下文条目上设置它(以与上面相同的方式)。

Update: The JSESSIONID stuff here is only for older containers.更新:此处的 JSESSIONID 内容仅适用于较旧的容器。 Please use jt's currently accepted answer unless you are using < Tomcat 6.0.19 or < Tomcat 5.5.28 or another container that does not support HttpOnly JSESSIONID cookies as a config option.请使用 jt 当前接受的答案,除非您使用 < Tomcat 6.0.19 或 < Tomcat 5.5.28 或其他不支持 HttpOnly JSESSIONID cookie 作为配置选项的容器。

When setting cookies in your app, use在您的应用程序中设置 cookie 时,请使用

response.setHeader( "Set-Cookie", "name=value; HttpOnly");

However, in many webapps, the most important cookie is the session identifier, which is automatically set by the container as the JSESSIONID cookie.但是,在许多 webapp 中,最重要的 cookie 是会话标识符,它由容器自动设置为 JSESSIONID cookie。

If you only use this cookie, you can write a ServletFilter to re-set the cookies on the way out, forcing JSESSIONID to HttpOnly.如果只使用这个cookie,可以写一个ServletFilter在出路时重新设置cookie,强制JSESSIONID为HttpOnly。 The page at http://keepitlocked.net/archive/2007/11/05/java-and-httponly.aspx http://alexsmolen.com/blog/?p=16 suggests adding the following in a filter. 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" );
} 

but note that this will overwrite all cookies and only set what you state here in this filter.但请注意,这将覆盖所有 cookie,并且只会设置您在此过滤器中声明的内容。

If you use additional cookies to the JSESSIONID cookie, then you'll need to extend this code to set all the cookies in the filter.如果您对 JSESSIONID cookie 使用其他 cookie,则需要扩展此代码以设置过滤器中的所有 cookie。 This is not a great solution in the case of multiple-cookies, but is a perhaps an acceptable quick-fix for the JSESSIONID-only setup.在多个 cookie 的情况下,这不是一个很好的解决方案,但对于 JSESSIONID-only 设置可能是一个可接受的快速修复。

Please note that as your code evolves over time, there's a nasty hidden bug waiting for you when you forget about this filter and try and set another cookie somewhere else in your code.请注意,随着您的代码随着时间的推移而发展,当您忘记此过滤器并尝试在代码中的其他位置设置另一个 cookie 时,会有一个令人讨厌的隐藏错误等着您。 Of course, it won't get set.当然,它不会被设置。

This really is a hack though.这确实是一个黑客。 If you do use Tomcat and can compile it, then take a look at Shabaz's excellent suggestion to patch HttpOnly support into Tomcat.如果您确实使用 Tomcat 并且可以编译它,那么请查看 Shabaz 的极好建议,将 HttpOnly 支持修补到 Tomcat 中。

Please be careful not to overwrite the ";secure" cookie flag in https-sessions.请注意不要覆盖 https 会话中的 ";secure" cookie 标志。 This flag prevents the browser from sending the cookie over an unencrypted http connection, basically rendering the use of https for legit requests pointless.此标志可防止浏览器通过未加密的 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);
    }
}

If your web server supports Serlvet 3.0 spec, like tomcat 7.0+, you can use below in web.xml as:如果您的 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>

As mentioned in docs:如文档中所述:

HttpOnly : Specifies whether any session tracking cookies created by this web application will be marked as HttpOnly HttpOnly :指定此 Web 应用程序创建的任何会话跟踪 cookie 是否将标记为 HttpOnly

Secure : Specifies whether any session tracking cookies created by this web application will be marked as secure even if the request that initiated the corresponding session is using plain HTTP instead of HTTPS Secure :指定即使发起相应会话的请求使用普通 HTTP 而不是 HTTPS,此 Web 应用程序创建的任何会话跟踪 cookie 是否也将标记为安全

Please refer to how to set httponly and session cookie for java web application请参阅如何为 java web 应用程序设置 httponly 和 session cookie

For session cookies it doesn't seem to be supported in Tomcat yet.对于会话 cookie,Tomcat 似乎尚不支持它。 See the bug report Need to add support for HTTPOnly session cookie parameter .请参阅错误报告需要添加对 HTTPOnly 会话 cookie 参数的支持 A somewhat involved work-around for now can be found here , which basically boils down to manually patching Tomcat.现在可以在这里找到一个有点复杂的解决方法,它基本上归结为手动修补 Tomcat。 Can't really find an easy way to do it at this moment at this point I'm affraid.在这一点上我真的无法找到一种简单的方法来做到这一点,我很害怕。

To summarize the work-around, it involves downloading the 5.5 source , and then change the source in the following places:总结一下解决方法,它涉及下载 5.5,然后在以下位置更改源:

org.apache.catalina.connector.Request.java 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 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);
}

For cookies that I am explicitly setting, I switched to use SimpleCookie provided by Apache Shiro .对于我明确设置的 cookie,我改用了Apache Shiro提供的SimpleCookie It does not inherit from javax.servlet.http.Cookie so it takes a bit more juggling to get everything to work correctly however it does provide a property set HttpOnly and it works with Servlet 2.5.它不是从 javax.servlet.http.Cookie 继承的,所以它需要更多的杂耍才能使一切正常工作,但是它确实提供了一个属性集 HttpOnly 并且它可以与 Servlet 2.5 一起使用。

For setting a cookie on a response, rather than doing response.addCookie(cookie) you need to do cookie.saveTo(request, response) .要在响应上设置 cookie,而不是执行response.addCookie(cookie)您需要执行cookie.saveTo(request, response)

also it should be noted that turning on HttpOnly will break applets that require stateful access back to the jvm.还应该注意的是,打开 HttpOnly 会破坏需要有状态访问回 jvm 的小程序。

the Applet http requests will not use the jsessionid cookie and may get assigned to a different tomcat. Applet http 请求不会使用 jsessionid cookie,并且可能会被分配给不同的 tomcat。

I Found in OWASP我在OWASP 中找到

<session-config>
  <cookie-config>
    <http-only>true</http-only>
  </cookie-config>
</session-config>

this is also fix for "httponlycookies in config" security issue这也是“配置中的httponlycookies”安全问题的修复

In Tomcat6, You can conditionally enable from your HTTP Listener Class:在 Tomcat6 中,您可以有条件地从您的 HTTP 侦听器类启用:

public void contextInitialized(ServletContextEvent event) {                 
   if (Boolean.getBoolean("HTTP_ONLY_SESSION")) HttpOnlyConfig.enable(event);
}

Using this class使用这个类

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();
        }
    }
}

Implementation: in Tomcat 7.x/8.x/9.x实现:在Tomcat 7.x/8.x/9.x

Go to Tomcat >> conf folder Open web.xml and add below in session-config section转到 Tomcat >> conf 文件夹打开 web.xml 并在 session-config 部分添加以下内容

    <cookie-config>
        <http-only>true</http-only>
        <secure>true</secure>
    </cookie-config>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM