Scenario
- I restart the server and browser so there's no session data.
- I go to www.someurl.com public access page. My controller gets me a session with this
HttpSession session=request.getSession(true);
- I click on a plane anchor link to www.someurl.com/admin restricted access page which opens in a new tab. Spring Security 3 intercepts this and challenges for credentials. I log in successfully.
- I go back to the previous tab with www.someurl.com and refresh the page.
Problem
What I notice in my controller for www.someurl.com is that the session id is different on step 2 and step 4. Looks like Spring Security created a new session and that session is now attached to the request for public page. Why does this happen and can I force Spring Security to use existing session?
Traced scenario
- Restart browser and server so no session data exist(s).
- I go to www.someurl.com. Controller has request injected. request.session is null. getSession(true) gets me a session with id 87B091B12F38D44C53AF0DA9E2147484. LogService gets the request object and also does getSession(true) but gets session with id 87B091B12F38D44C53AF0DA9E2147484 so all's good thus far.
- I click /admin. Page opens up in new tab. I log in.
- I refresh the www.someurl.com. Controller has request injected. request.session is not null. Session id is 547DF59035C91783D783BAEF4A15FBFF.
You need to change the behavior of
HttpSessionRequestCache
so that it doesn't create a session if one does not exist.You can do it by creating its instance in your XML configuration as below:
Then you need to configure the http element in your spring security config to use your bean instance:
If you're using JSP, you should also prevent the JSP from creating a session. In order to do it, you need to add a
page
directive on top of every JSP (even the ones that are included from other JSP's).You got your diagnostic wrong:
It's precisely because all the pages use the same session that when you go back to the first tab and refresh, you're still logged in as an admin. All the tabs and frames of a given browser share the same session for a given webapp. That's how it works. The server doesn't know and care about browser tabs. It gets a session cookie attached to all the requests sent by a given browser, and uses this cookie to get the corresponding session. This is actually a good thing. Without that, each time you open a new tab once already authenticated, you would have to authenticate again. And you definitely don't want that.
So let's explain what happens in your scenario:
EDIT: it appears I was wrong, and Spring indeed creates a new session after login to prevent session fixation attacks. Explanations about why this is useful, and how to avoid this behavior are available in the documentation: