Index: connectors/util/java/org/apache/tomcat/util/http/ServerCookie.java =================================================================== --- connectors/util/java/org/apache/tomcat/util/http/ServerCookie.java (revision 765287) +++ connectors/util/java/org/apache/tomcat/util/http/ServerCookie.java (working copy) @@ -242,7 +242,8 @@ String domain, String comment, int maxAge, - boolean isSecure ) + boolean isSecure, + boolean isHttpOnly) { StringBuffer buf = new StringBuffer(); // Servlet implementation checks name @@ -302,6 +303,10 @@ buf.append ("; Secure"); } + // HttpOnly + if (isHttpOnly) { + buf.append("; HttpOnly"); + } headerBuf.append(buf); } Index: container/catalina/src/share/org/apache/catalina/connector/Request.java =================================================================== --- container/catalina/src/share/org/apache/catalina/connector/Request.java (revision 763174) +++ container/catalina/src/share/org/apache/catalina/connector/Request.java (working copy) @@ -2238,7 +2238,7 @@ Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME, session.getIdInternal()); configureSessionCookie(cookie); - response.addCookie(cookie); + response.addCookieInternal(cookie, context.getUseHttpOnly()); } if (session != null) { Index: container/catalina/src/share/org/apache/catalina/connector/Response.java =================================================================== --- container/catalina/src/share/org/apache/catalina/connector/Response.java (revision 763174) +++ container/catalina/src/share/org/apache/catalina/connector/Response.java (working copy) @@ -932,7 +932,18 @@ * @param cookie Cookie to be added */ public void addCookie(final Cookie cookie) { + addCookieInternal(cookie, false); + } + /** + * Add the specified Cookie to those that will be included with + * this Response. + * + * @param cookie Cookie to be added + * @param httpOnly Should the httpOnly flag be set on this cookie + */ + public void addCookieInternal(final Cookie cookie, final boolean httpOnly) { + if (isCommitted()) return; @@ -950,7 +961,8 @@ (sb, cookie.getVersion(), cookie.getName(), cookie.getValue(), cookie.getPath(), cookie.getDomain(), cookie.getComment(), - cookie.getMaxAge(), cookie.getSecure()); + cookie.getMaxAge(), cookie.getSecure(), + httpOnly); return null; } }); @@ -958,7 +970,7 @@ ServerCookie.appendCookieValue (sb, cookie.getVersion(), cookie.getName(), cookie.getValue(), cookie.getPath(), cookie.getDomain(), cookie.getComment(), - cookie.getMaxAge(), cookie.getSecure()); + cookie.getMaxAge(), cookie.getSecure(), httpOnly); } // if we reached here, no exception, cookie is valid Index: container/catalina/src/share/org/apache/catalina/Context.java =================================================================== --- container/catalina/src/share/org/apache/catalina/Context.java (revision 763174) +++ container/catalina/src/share/org/apache/catalina/Context.java (working copy) @@ -181,8 +181,24 @@ */ public void setCookies(boolean cookies); + /** + * Gets the value of the use HttpOnly cookies for session cookies flag. + * + * @return true if the HttpOnly flag should be set on session + * cookies + */ + public boolean getUseHttpOnly(); + /** + * Sets the use HttpOnly cookies for session cookies flag. + * + * @param useHttpOnly Set to true to use HttpOnly cookies + * for session cookies + */ + public void setUseHttpOnly(boolean useHttpOnly); + + /** * Return the "allow crossing servlet contexts" flag. */ public boolean getCrossContext(); Index: container/catalina/src/share/org/apache/catalina/core/StandardContext.java =================================================================== --- container/catalina/src/share/org/apache/catalina/core/StandardContext.java (revision 763174) +++ container/catalina/src/share/org/apache/catalina/core/StandardContext.java (working copy) @@ -656,6 +656,10 @@ */ private boolean saveConfig = true; + /** + * The flag that indicates that session cookies should use HttpOnly + */ + private boolean useHttpOnly = false; // ----------------------------------------------------- Context Properties @@ -1045,9 +1049,36 @@ new Boolean(this.cookies)); } + + /** + * Gets the value of the use HttpOnly cookies for session cookies flag. + * + * @return true if the HttpOnly flag should be set on session + * cookies + */ + public boolean getUseHttpOnly() { + return useHttpOnly; + } /** + * Sets the use HttpOnly cookies for session cookies flag. + * + * @param useHttpOnly Set to true to use HttpOnly cookies + * for session cookies + */ + public void setUseHttpOnly(boolean useHttpOnly) { + boolean oldUseHttpOnly = this.useHttpOnly; + this.useHttpOnly = useHttpOnly; + support.firePropertyChange("useHttpOnly", + new Boolean(oldUseHttpOnly), + new Boolean(this.useHttpOnly)); + } + + + + + /** * Return the "allow crossing servlet contexts" flag. */ public boolean getCrossContext() { Index: container/webapps/docs/changelog.xml =================================================================== --- container/webapps/docs/changelog.xml (revision 763174) +++ container/webapps/docs/changelog.xml (working copy) @@ -54,6 +54,10 @@ 42419: Add a system property that enables the name of the session cookie and session path parameter to be configured. (markt) + + 44382: Add support for using httpOnly for session cookies. + This is disabled by default. (markt/fhanik) + 45576: JAAS Realm now works with DIGEST authentication. (markt) Index: container/webapps/docs/config/context.xml =================================================================== --- container/webapps/docs/config/context.xml (revision 763174) +++ container/webapps/docs/config/context.xml (working copy) @@ -235,6 +235,13 @@ implementation class that will be used for servlets managed by this Context. If not specified, a standard default value will be used.

+ + +

Should the HttpOnly flag be set on session cookies to prevent client + side script from accessing the session ID? Defaults to + false.

+
+