Tutorials Logic, IN info@tutorialslogic.com

Servlet Session Management HttpSession, Cookies, URL Rewriting

Session Identity Flow

HTTP does not remember earlier requests. HttpSession gives the server a per-client state container and associates later requests with it through a session identifier, usually carried in a cookie. The cookie contains an opaque identifier, while application values such as the user id or cart state remain on the server.

A secure session design creates state only when needed, rotates the identifier after authentication, stores the smallest useful values, expires inactive sessions, and invalidates the session during logout. It must also handle clients that reject cookies without exposing identifiers carelessly.

Create Read Invalidate

getSession() returns the current session or creates one. getSession(false) returns the current session or null and is the right choice for endpoints that should not create anonymous state. setAttribute() binds an application object to a name; getAttribute() returns it or null; invalidate() ends the session and unbinds its attributes.

Session attributes may be accessed by concurrent requests from the same browser, so mutable objects stored in a session need careful design. Prefer small immutable identifiers and load current business data from an authoritative service rather than storing an entire editable domain object for hours.

Login, Account Check, and Logout

Login, Account Check, and Logout
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import java.io.IOException;

@WebServlet("/account/*")
public class AccountServlet extends HttpServlet {
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        if ("/login".equals(req.getPathInfo())) {
            // Validate credentials before this point.
            HttpSession session = req.getSession(true);
            req.changeSessionId();
            session.setAttribute("userId", 42L);
            session.setMaxInactiveInterval(30 * 60);
            resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
            return;
        }

        HttpSession session = req.getSession(false);
        if (session != null) session.invalidate();
        resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
    }
}

Cookie Transport

Containers commonly transport the session id in a cookie such as JSESSIONID. Configure the session cookie as HttpOnly so scripts cannot read it, Secure so it is sent only over HTTPS, and with an appropriate SameSite policy at the server or deployment layer. These settings reduce exposure but do not replace authorization or CSRF protection.

Never put a password, access token, personal profile, or serialized application state into the session-id cookie. A stolen valid identifier can let another client act as the session owner until the session expires or is invalidated.

Cookie Management and URL Rewriting

Cookie Management and URL Rewriting
@WebServlet("/cookie-demo")
public class CookieServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        // ===== Create Cookie =====
        Cookie userCookie = new Cookie("username", "Alice");
        userCookie.setMaxAge(7 * 24 * 60 * 60); // 7 days
        userCookie.setPath("/");
        userCookie.setHttpOnly(true);   // Prevent XSS
        userCookie.setSecure(true);     // HTTPS only
        resp.addCookie(userCookie);

        // ===== Read Cookies =====
        Cookie[] cookies = req.getCookies();
        String username = null;
        if (cookies != null) {
            for (Cookie c : cookies) {
                if ("username".equals(c.getName())) {
                    username = c.getValue();
                    break;
                }
            }
        }

        // ===== Delete Cookie =====
        Cookie deleteCookie = new Cookie("username", "");
        deleteCookie.setMaxAge(0); // Expire immediately
        deleteCookie.setPath("/");
        // resp.addCookie(deleteCookie); // Uncomment to delete

        // ===== URL Rewriting (fallback when cookies disabled) =====
        String encodedUrl = resp.encodeURL(req.getContextPath() + "/profile");
        // Appends ;jsessionid=... if cookies are disabled

        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        out.println("<p>Username from cookie: " + username + "</p>");
        out.println("<a href='" + encodedUrl + "'>My Profile</a>");
    }
}

Fixation and Rotation

Session fixation happens when an attacker causes a victim to authenticate while using an identifier already known to the attacker. After successful authentication or another major privilege change, call changeSessionId() so the authenticated session uses a fresh identifier while its attributes remain available.

Logout should invalidate server-side state, clear authentication cookies as appropriate, and avoid redirects to attacker-controlled locations. Password changes, account recovery, and administrator impersonation flows may also justify rotating or revoking sessions.

  • Rotate after authentication, not before credential validation.
  • Do not accept a session identifier from an ordinary query parameter.
  • Set an inactivity timeout that matches the sensitivity of the application.
  • Provide a way to revoke sessions after a security event.

URL Rewriting Fallback

If cookie-based tracking is unavailable, a servlet container can encode the session identifier into application URLs. Pass internal links through response.encodeURL() and redirects through encodeRedirectURL(); the container decides whether rewriting is necessary.

URL-based identifiers can leak through browser history, copied links, logs, analytics, and Referer headers. Prefer secure cookies, avoid URL rewriting for sensitive applications when possible, and never hand-build a ;jsessionid value.

Container-Aware Session Link

Container-Aware Session Link
String cartUrl = resp.encodeURL(req.getContextPath() + "/cart");
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().printf("<a href=\"%s\">Cart</a>", cartUrl);
Before you move on

Session Security Review

5 checks
  • Use getSession(false) when an anonymous request should not create state.
  • Rotate the session id after login or another privilege change.
  • Store compact identifiers instead of large mutable business objects.
  • Configure secure cookie attributes and an appropriate inactivity timeout.
  • Invalidate the session on logout and security-sensitive revocation.

Session Design Failures

  • Creating sessions on every page

    Use getSession(false) for read-only checks and create a session only when state is needed.
  • Keeping the same id after login

    Call changeSessionId() after authentication succeeds.
  • Putting secrets in URL rewriting

    Let encodeURL handle only the opaque session id and prefer secure cookies.

Try this next

Build a Session Lifecycle

0 of 3 completed

  1. Return 401 without creating a session when getSession(false) returns null.
  2. Record the identifier before and after changeSessionId() in a local test and confirm the user attribute survives.
  3. Set a short test timeout, observe expiry, then implement explicit invalidation.

Session Lifecycle Questions

No. HttpSession is server-managed state; a cookie commonly transports the opaque identifier that links a request to that state.

The session becomes invalid and its bound attributes are removed. A later getSession() call can create a different session.

No. Store compact serializable state and obtain short-lived infrastructure resources from managed services or pools.

Next Step
Next Practice

Finish the concept here, then reinforce it with hands-on coding, interview prep, or a tool that matches the topic.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.