The difference of set cookie in Tomcat and Jetty
Published in:2025-04-25 | Category: Backend
Words: 1.1k | Reading time: 7min

In previous blog Switching Tomcat with Jetty in Spring Boot Easily, to resolve the spring boot 2 tomcat security issue in short time, we switching Tomcat with Jetty in Spring Boot. We found there is a difference by set cookie handling between Tomcat and Jetty by default. Let’s first talk about the cookie.

A cookie is a small piece of data that is stored on the user’s computer by the web server. It is used to store user preferences, login information, and other information that the user wants to be remembered. The cookie is sent to the user’s browser when the user makes a request to the web server. The browser then sends it back to the web server with subsequent requests.

There are several attributes that can be set for a cookie:

  • Domain: The domain attribute specifies the domain for which the cookie is valid. If the domain is not specified, the cookie is valid for the entire domain.
  • Path: The path attribute specifies the path on the server where the cookie is valid. If the path is not specified, the cookie is valid for the entire path.
  • Max-Age: The max-age attribute specifies the maximum age of the cookie in seconds. If the max-age is not specified, the cookie is valid until the browser is closed.
  • Expires: The expires attribute specifies the expiration date of the cookie. If the expires attribute is not specified, the cookie is valid until the browser is closed.
  • Secure: The secure attribute specifies that the cookie should only be sent over HTTPS connections.
  • HttpOnly: The httpOnly attribute specifies that the cookie should not be accessible to client-side scripts.
  • SameSite: The sameSite attribute specifies whether the cookie should be sent with cross-site requests. The sameSite attribute can have the following values: Strict, Lax, or None.

When Max-Age and Expires are not specified, the cookie is valid until the browser is closed. If Max-Age is specified, the cookie is valid for the specified number of seconds. If Expires is specified, the cookie is valid until the specified date. If both Max-Age and Expires are specified, the cookie is valid for the minimum of the two values.

In Spring Boot, the Set-Cookie header is used to send cookies to the user’s browser. The Set-Cookie header is sent in the response to the user’s request. The Set-Cookie header contains the name, value, and other attributes of the cookie. Here is an example of the Set-Cookie header in Spring Boot:

1
Set-Cookie: JSESSIONID=1234567890; Path=/; HttpOnly; Secure

In this example, the JSESSIONID is the name of the cookie, 1234567890 is the value of the cookie, Path is the path on the server where the cookie is valid, / is the path, HttpOnly is a flag that indicates that the cookie should not be accessible to client-side scripts, Secure is a flag that indicates that the cookie should only be sent over HTTPS connections, and SameSite is not set.

In Network tab of Chrome DevTools, we can see the Set-Cookie header in the response headers. That means these cookie are set by web server and sent to the user’s browser and stored in the user’s computer.

Set-Cookie in response headersSet-Cookie in response headers
Set-Cookie in response headers

And we can also see the cookies in Application tab of Chrome DevTools. The cookies are stored in the user’s browser and can be accessed by the web server in subsequent requests.

Cookies in Browser Application tabCookies in Browser Application tab
Cookies in Browser Application tab

Okay, let’s talk about the difference of Set-Cookie header handling between Tomcat and Jetty. Here we will use curl command to send a request to the server and see the Set-Cookie header in the response for default configuration.

Tomcat

If we want to reduce XSS cross-site scripting attacks and prevent reading and modifying cookie contents, we can set the HttpOnly attribute for the cookie. In Tomcat 6, we need to config it in the tomcat/conf/context.xml file. Add the useHttpOnly="true" attribute in <Context> tag.

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

But for Tomcat 7 and later version. We don’t need to config it in context.xml any more. The useHttpOnly attribute is set to true by default. It is introduced in Tomcat 7 official doc (https://tomcat.apache.org/tomcat-7.0-doc/config/context.html)

HttpOnly in Tomcat 7HttpOnly in Tomcat 7
HttpOnly in Tomcat 7

Below is the screenshot that using curl command to send a request to our current Spring Boot application with Tomcat server:

Set-Cookie with HttpOnlySet-Cookie with HttpOnly
Set-Cookie with HttpOnly

From the screenshot, you can see the Set-Cookie header in the response. The HttpOnly attribute is appended in the cookie by default.

BTW, from Spring Boot 2 version, it is starting use Tomcat 8 version which will set HttpOnly attribute by default in the cookie.

Jetty

For Jetty, the HttpOnly attribute is not set by default. We need to config it in the web.xml file. Add the <http-only> element in <cookie-config> tag.

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

We also can set the HttpOnly attribute for the cookie in the code.

1
SessionCookieConfig.setHttpOnly(true);

We can find the evidence in the Jetty official doc https://jetty.org/docs/jetty/12/programming-guide/server/session.html.

HttpOnly in JettyHttpOnly in Jetty
HttpOnly in Jetty

By default, the HttpOnly attribute is not set in the Set-Cookie header in jetty. Below is the screenshot that using curl command to send a request to our current Spring Boot application with Jetty server by default configuration:

Set-Cookie without HttpOnlySet-Cookie without HttpOnly
Set-Cookie without HttpOnly

As you can see, the HttpOnly attribute is not set in the Set-Cookie header in Jetty by default when we use the curl command. The code are same, just simply switch Tomcat to Jetty in the pom.xml file in previous blog.

Summary

The Set-Cookie header is used to send cookies to the user’s browser. The HttpOnly attribute is used to prevent client-side scripts from accessing the cookie. The Secure attribute is used to ensure that the cookie is only sent over HTTPS connections. The SameSite attribute is used to prevent cross-site requests. The difference of Set-Cookie header handling between Tomcat and Jetty is that Tomcat set the HttpOnly attribute by default, while Jetty does not set it by default. We need to config it in the web.xml file for Jetty or set it in the code for Tomcat. So when you switche Tomcat to Jetty, you need to check the HttpOnly attribute in the Set-Cookie header for session id for security reason.

Prev:
Understanding the Model Context Protocol (MCP)
Next:
Traditional Programming vs Artificial Intelligence