首页 / 知识

关于安全性:如何在tomcat / java webapps中配置HttpOnly cookie?

2023-04-13 13:27:00

关于安全性:如何在tomcat / java webapps中配置HttpOnly cookie?

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

阅读Jeff关于保护您的Cookies的博客文章: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中为所有Web应用程序启用httpOnly功能:

1
2
3
<Context useHttpOnly="true">
...
</Context>

我的解释是,通过将其设置在conf / server.xml中所需的Context条目上,它也适用于单个上下文(与上述方法相同)。


Update: The JSESSIONID stuff here is
only for older containers. 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.

在您的应用中设置Cookie时,请使用

1
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建议添加在过滤器中。

1
2
3
4
5
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时,会有一个令人讨厌的隐藏错误等待着您。当然,它不会被设置。

这确实是一个hack。如果您确实使用Tomcat并且可以编译它,那么请看一下Shabaz关于将HttpOnly支持修补到Tomcat中的出色建议。


请注意不要覆盖https-sessions中的"; secure" cookie标志。此标志可防止浏览器通过未加密的http连接发送cookie,从而使对合法请求的HTTP使用变得毫无意义。

1
2
3
4
5
6
7
8
9
10
11
12
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);
    }
}


如果您的Web服务器支持Serlvet 3.0规范,例如tomcat 7.0+,则可以在web.xml中使用以下代码:

1
2
3
4
5
6
<session-config>
  <cookie-config>
     <http-only>true</http-only>        
     <secure>true</secure>        
  </cookie-config>
</session-config>

如文档中所述:

HttpOnly: Specifies whether any session tracking cookies created by
this web application will be marked as 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

请参考如何为Java Web应用程序设置httponly和会话cookie


对于会话cookie,Tomcat似乎尚不支持它。请参阅错误报告。需要添加对HTTPOnly会话cookie参数的支持。现在可以在这里找到一些涉及的变通方法,基本上可以归结为手动修补Tomcat。目前,我感到非常震惊,目前还无法找到一种简单的方法。

总结一下解决方法,它涉及下载5.5源,然后在以下位置更改源:

org.apache.catalina.connector.Request.java

1
2
3
4
5
6
//this is what needs to be changed
//response.addCookieInternal(cookie);

//this is whats new
response.addCookieInternal(cookie, true);
}

org.apache.catalina.connectorResponse.addCookieInternal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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);
}

我在OWASP中找到

1
2
3
4
5
<session-config>
  <cookie-config>
    <http-only>true</http-only>
  </cookie-config>
</session-config>

这也解决了"配置中的httponlycookies"安全问题


对于我明确设置的Cookie,我改用了Apache Shiro提供的SimpleCookie。它没有继承自javax.servlet.http.Cookie,因此要使一切正常工作还需要花费一些时间,但是它确实提供了HttpOnly属性集,并且可以与Servlet 2.5一起使用。

要在响应上设置Cookie,而不是执行response.addCookie(cookie),您需要执行cookie.saveTo(request, response)


还应该注意的是,打开HttpOnly将破坏需要状态访问jvm的applet。

Applet http请求将不会使用jsessionid cookie,并且可能会分配给其他tomcat。


在Tomcat6中,您可以有条件地从HTTP侦听器类启用:

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

使用本课程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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();
        }
    }
}


配置安全性博客应用程序

最新内容

相关内容

热门文章

推荐文章

标签云

猜你喜欢