Compare the session-fixation strategies (changeSessionId, migrateSession, newSession, none) and when each is appropriate.
answer
- changeSessionId = same session, new ID (default)
- migrateSession = new session, copy attributes
- newSession = new session, no copy (clean slate)
- none = disabled = vulnerable
- Servlet 3.1+ enables changeSessionId
basics
~10 schangeSessionId keeps the session and its data but gives it a new ID (default). migrateSession makes a new session and copies attributes. newSession makes a fresh empty session. none disables rotation and is unsafe.
solid answer
~40 sAll non-`none` strategies rotate the session identity at login to defeat fixation. changeSessionId() (default on Servlet 3.1+) keeps the same HttpSession object and attributes but has the container assign a new ID via HttpServletRequest.changeSessionId() — cheapest, preserves state. migrateSession() creates a brand-new session and copies the old attributes over; used on containers lacking changeSessionId support (pre-Servlet-3.1). newSession() creates a fresh session but does not copy application attributes (only a couple of Spring Security internals), giving a clean slate at login. none() disables fixation protection — the ID stays the same, reopening the vulnerability, so it's essentially never right unless an external layer guarantees rotation. On any modern container, accept the default changeSessionId(). Pick newSession() when you deliberately want to drop pre-login state; migrateSession() only for legacy containers.
code
java · 7 lineshttp.sessionManagement(session -> session
// pick ONE:
.sessionFixation(f -> f.changeSessionId()) // default: same session, new ID
// .sessionFixation(f -> f.migrateSession()) // new session, attributes copied
// .sessionFixation(f -> f.newSession()) // new empty session, no copy
// .sessionFixation(f -> f.none()) // DISABLED - avoid
);go deeper
Know changeSessionId is the default and none disables protection.
Contrast all four on new-object vs attribute-copy behavior.
Tie strategy choice to concurrent-session tracking and HttpSessionIdChangedEvent.
Reason about distributed session stores and custom trackers reacting to ID changes, and policy reasons to drop pre-login state.
**Why rotate at all.** Session fixation is defeated by ensuring the session identifier changes when the user's privilege level changes (login). All strategies except `none()` do this; they differ in *how they treat the session object and its attributes*. **The four strategies** (`sessionManagement { sessionFixation { ... } }`): | Strategy | New ID? | Same HttpSession object? | Attributes preserved? | Backing mechanism | |---|---|---|---|---| | `changeSessionId()` **(default)** | Yes | Yes (same object) | Yes | `HttpServletRequest.changeSessionId()` (Servlet 3.1+) | | `migrateSession()` | Yes | No (new session) | Yes (copied) | Manual create + copy attributes | | `newSession()` | Yes | No (new session) | No (only SS internals) | Manual create, no copy | | `none()` | No | Yes | Yes | Protection disabled | **Details & rationale.** - **`changeSessionId()`** — Introduced as the default from Spring Security 4 on Servlet 3.1+ containers. It's the least disruptive: the same `HttpSession` continues, attributes are untouched, only the container-issued ID changes. Fires `HttpSessionIdChangedEvent`. Preferred everywhere modern. - **`migrateSession()`** — Was the default before Servlet 3.1. Invalidates the old session, creates a new one, and copies attributes across. Slightly heavier; needed only where `changeSessionId()` isn't available. - **`newSession()`** — Like migrate but *does not copy* application attributes (a few Spring Security-owned attributes such as saved-request may carry). Use when security policy says pre-authentication state must be discarded at login (e.g. to avoid smuggling data set by an anonymous user into the authenticated session). - **`none()`** — Turns protection off; the session ID is not rotated. Only defensible if an upstream component already rotates IDs; otherwise it's a vulnerability. **Gotchas.** - Components that key off the session ID (Spring Session, `SessionRegistry` for concurrent-session control) must react to the ID change; Spring Security's concurrent-control wiring handles `changeSessionId()`. Custom trackers may need to listen for `HttpSessionIdChangedEvent`. - Under `SessionCreationPolicy.STATELESS` these strategies are irrelevant — no session is created to fix. - `newSession()` surprising data loss: attributes set before login vanish; don't rely on them post-login. **When to use which.** Default `changeSessionId()` for virtually all apps. `newSession()` for a deliberate clean slate. `migrateSession()` only for pre-Servlet-3.1 containers. Avoid `none()`.
- Which strategy would you choose if you must discard any attributes an anonymous user set before login?newSession() — it creates a fresh session and does not copy application attributes, so pre-login data is dropped (only a few Spring Security internals carry over).
- Why is changeSessionId() preferred over migrateSession() on modern containers?It keeps the same HttpSession object and attributes and only changes the ID via Servlet 3.1's changeSessionId(), avoiding the cost and edge cases of recreating a session and copying attributes.
saying these in an interview costs you the question
- Saying migrateSession() and newSession() behave identically (they differ on attribute copying).
- Recommending none() as a performance optimization.
- Thinking changeSessionId() creates a new HttpSession object (it reuses the same one).