【问题标题】:Setting an httponly cookie with javax.servlet 2.5使用 javax.servlet 2.5 设置 httponly cookie
【发布时间】:2012-10-20 06:31:24
【问题描述】:

这是一个设置 cookie 的函数:

public void addCookie(String cookieName, String cookieValue, Integer maxAge, HttpServletResponse response) {
    Cookie cookie = new Cookie(cookieName, cookieValue);
    cookie.setPath("/mycampaigns");
    cookie.setSecure(isSecureCookie);
    cookie.setMaxAge(maxAge);
    response.addCookie(cookie);
}

我相信 servlet 3.0,有办法直接做到这一点。不幸的是,我的组织使用 2.5,此时升级不是一种选择。

有没有办法使用响应来设置cookie?这是我在网上找到的一个例子

response.setHeader("SET-COOKIE", "[SOME STUFF]" +"; HttpOnly")

如果这是做我想做的唯一方法,我会用什么替换“[SOME STUFF]”,这样我就不会丢失我的函数当前存储在 cookie 中的任何数据?

【问题讨论】:

标签: java cookies cookie-httponly servlet-2.5


【解决方案1】:

你是对的,手动设置标题是实现目标的正确方法。

您还可以使用 javax.ws.rs.core.NewCookie 或任何其他具有有用 toString 方法的类将 cookie 打印到标头以使事情更简单。

public static String getHttpOnlyCookieHeader(Cookie cookie) {

    NewCookie newCookie = new NewCookie(cookie.getName(), cookie.getValue(), 
            cookie.getPath(), cookie.getDomain(), cookie.getVersion(), 
            cookie.getComment(), cookie.getMaxAge(), cookie.getSecure());

    return newCookie + "; HttpOnly";
}

及用法:

response.setHeader("SET-COOKIE", getHttpOnlyCookieHeader(myOriginalCookie));

【讨论】:

  • 我在哪里设置这个类?或者我该如何配置?
  • 感谢@Val,但我仍然有疑问,我看到了该类及其所有属性,但是,如何在我的应用程序上启用它?
  • 有点晚了,但是从 2.0 开始,javax.ws.rs.core.NewCookie 有一个带有 httpOnly 的构造函数,你不需要将它附加到 toString() :NewCookie nc = new NewCookie("name ","value","path","domain","comment",3600,true, true);
【解决方案2】:

此代码不使用response.setHeader()

public void addCookie(String cookieName, String cookieValue, Integer maxAge, HttpServletResponse response) {  
    Cookie cookie = new Cookie(cookieName, cookieValue);
    cookie.setPath("; HttpOnly;");
    cookie.setSecure(isSecureCookie);
    cookie.setMaxAge(maxAge);
    response.addCookie(cookie);
}

【讨论】:

  • 当我需要使用路径 "/" 并使用 cookie.setPath("/; HttpOnly;") 时,它会生成带有 Path="/; HttpOnly;" 的 cookie并且 Chrome 错误地将路径评估为“/ 值(注意引号)。即使我首先赞成这个答案,但我最终在这里得到了另一个答案,它使用了 getHttpOnlyCookieHeader(...) 辅助方法。
【解决方案3】:

对于 JEE 6 之前的 Java Enterprise Edition 版本,例如 Servlet 2.5,您可以从 OWASP 的here 找到解决方法。下面是一个例子:

    /**
     * Issue a cookie to the browser
     * 
     * @param response
     * @param cookieName
     * @param cookieValue
     * @param cookiePath
     * @param maxAgeInSeconds
     */
    public static void issueCookieHttpOnly(HttpServletResponse response, 
            String cookieName, 
            String cookieValue, 
            String cookiePath, 
            long maxAgeInSeconds) {

        Date expireDate= new Date();
        expireDate.setTime (expireDate.getTime() + (1000 * maxAgeInSeconds));
        // The following pattern does not work for IE.
        // DateFormat df = new SimpleDateFormat("dd MMM yyyy kk:mm:ss z");

        // This pattern works for Firefox, Chrome, Safari and Opera, as well as IE.
        DateFormat df = new SimpleDateFormat("EEE, dd-MMM-yyyy kk:mm:ss z");
        df.setTimeZone(TimeZone.getTimeZone("GMT"));
        String cookieExpire = df.format(expireDate);

        StringBuilder sb = new StringBuilder(cookieName);
        sb.append("=");
        sb.append(cookieValue);
        sb.append(";expires=");
        sb.append(cookieExpire);
        sb.append(";path=");
        sb.append(cookiePath);
        sb.append(";HttpOnly");

        response.setHeader("SET-COOKIE", sb.toString());
    }

【讨论】:

    【解决方案4】:

    如果你不想使用:

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

    那么您可以在 servlet 2.5 中使用以下代码。它可以在 chromefirefoxIE11 中完美运行。

    Cookie cookie = new Cookie(cookieName, cookieValue);
    
    cookie.setPath(";Path=/;HttpOnly;");
    cookie.setSecure(isSecureCookie);
    cookie.setMaxAge(maxAge);
    
    response.addCookie(cookie);
    

    注意:如您所知,我们在 servlet 2.5 版本中没有 setHttpOnly() 方法,因此您可以使用以下方法代替:

    setPath(";Path=/;HttpOnly;");
    

    它将创建一个路径为“/”的cookie,并将Cookie设为HttpOnly

    【讨论】:

      【解决方案5】:

      对于 Servlet API 2.5,您可以使用

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

      使用 response.setHeader() 时要小心,因为它会删除所有其他 cookie,例如 JSESSIONID cookie。

      【讨论】:

        【解决方案6】:

        Spring 使用反射来执行此操作,而不会破坏 servlet 2.5 容器。

        Method setHttpOnlyMethod = ReflectionUtils.findMethod(Cookie.class, "setHttpOnly", boolean.class);
        if (setHttpOnlyMethod != null) {
            ReflectionUtils.invokeMethod(setHttpOnlyMethod, cookie, Boolean.TRUE);      
        }
        

        但是 setHttpOnly 方法仅在 Servlet 3.0 及更高版本上可用。

        【讨论】:

        • 这不是一个好主意:如果您可以使用反射在您的生产/开发环境中找到 setHttpOnly 方法,那么您应该首先修复您的项目依赖项。这不是 OP 所要求的。
        • 在将 servlet 2.5 应用程序部署到 servlet 3.0+ 容器时,这对我有用。尝试在评论中附加 HttpOnly 不起作用,因为评论被引用了。我相信将它添加到路径中会产生相同的结果,但我没有尝试过。
        【解决方案7】:

        如果您不想硬编码HttpOnly; 或不喜欢添加标题,请像这样使用apache shiro

        void addCookie(javax.servlet.http.Cookie httpCookie,
                       HttpServletRequest request,
                       HttpServletResponse response) {
            org.apache.shiro.web.servlet.Cookie cookie =
                         new org.apache.shiro.web.servlet.SimpleCookie(httpCookie.getName());
        
            cookie.setValue(httpCookie.getValue());
            cookie.setPath(httpCookie.getPath());
            // set other stuff from the original httpCookie
            cookie.setHttpOnly(true);
        
            cookie.saveTo(request, response);
        }
        

        【讨论】:

          【解决方案8】:

          @Yuci 给响应头添加cookie的例子在我的环境中有些失败。主要是日期格式错误,如果您 addHeader 不会像 setHeader 那样删除其他 cookie。所以这是我使用 Servlet API 2.5 设置 HttpOnlySecure cookie 的工作代码:

          public static void addHttpOnlyCookie(HttpServletResponse response,
                                               String cookieName,
                                               String cookieValue,
                                               String cookiePath,
                                               long maxAgeInSeconds) {
          
              Date expireDate = new Date();
              expireDate.setTime(expireDate.getTime() + 1000L * maxAgeInSeconds);
              DateFormat df = new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss z", Locale.ENGLISH);
              df.setTimeZone(TimeZone.getTimeZone("GMT"));
              String cookieExpire = df.format(expireDate);
          
              StringBuilder sb = new StringBuilder(cookieName);
              sb.append("=");
              sb.append(cookieValue);
              sb.append("; Expires=");
              sb.append(cookieExpire);
              sb.append("; Path=");
              sb.append(cookiePath);
              sb.append("; Secure; HttpOnly");
          
              response.addHeader("SET-COOKIE", sb.toString());
          }
          

          请注意,这些setPath hack 肯定行不通。不要这样做,它们不适用于 Safari:cookie.setPath(";HttpOnly;");

          【讨论】:

            【解决方案9】:
            Cookie cookie = new Cookie("JSESSIONID", session.getId());
            cookie.setPath("/");
            cookie.setMaxAge(-1);
            response.addCookie(cookie);
            

            实际上,在我的情况下,这段代码并不完全有效。
            路径值不是"/"

            但是添加这个cookie.setComment("; HttpOnly;"); 可以正常工作!

            【讨论】:

            • 我试过了,它只是将 HttpOnly 放在引用的评论中,浏览器会忽略它。
            猜你喜欢
            • 2020-01-06
            • 1970-01-01
            • 1970-01-01
            • 2012-05-18
            • 2022-07-27
            • 2017-02-04
            • 2016-06-04
            • 2017-01-30
            相关资源
            最近更新 更多