I have a Java Website using Spring's MVC pattern. The frontend views are JSP files which use Java-Script and jQuery in numerous cases to allow for some smooth design, I guess.
Now, I realised a very specific bug that i wanted to get rid off the last few days but I cannot seem to understand how the given factors are causing it. It is really weird.
What causes the bug
- On any JSP that contains ajax-Javascript idle until Session-Timeout is reached
- Trigger the timeout by calling one of the ajax-Scripts (doesnt matter which, only matters that is is ajax)
- An automatic redirect to the login-page happens, as the server realises that the session was timed out by the time the request was done
- I logg back into the site and go back to where i previously had called the ajax-script
- I try to run that ajax-Script again and now am returned a wrong view. I basically have my mainpage returned instead of the usual desired view
I found where in my code this is caused. Each ajax-Script basically makes a POST or GET request to the server using a specific URL. And then i have a typcial Controller on the server that catches this request and procceses it (retrieving necessary data and then return the view supplied with Model-Data).
In all of those Controllers it is first checked whether or not a user is currently logged in. This is because basically all of the ajax-actions retrieve user-specific data and it wouldnt make sense to do so if there is no user logged in anymore. Apparently this check fails, as the result of this check failing explains why i get my mainpage returned. Instead of returning the right view with the right data i am returned a RedirectView onto "/login.html".
The reason i am now shown the Login-Page but my mainPage instead is most likely explained by the fact that the Controller listning to "/login.html" actually realises that a user IS infact logged in and thus returns my mainPage instead of the loginPage.
Note that each and every other controller other than the controller that is responsible for the ajax-Request that triggered the session-timeout continues working as expected! No bugs or weird behaviour with any other ajax or non-ajax Request!
Meaning that only the ajax-Script that had caused the session-timeout is not working. Every other ajax-Script is still working perfectly fine!
Logging back in and out has no effect, the ajax-Script continues to be bugged. In most cases i have to restart the browser in order to make it work again.
Weird stuff that i have found out using FF/IE network-tools
- Every ajax-call and ONLY the ajax-calls are sent by the browser using 2 different Cookies!
- Each of those Cookies contains a different JSESSIONID
- When observing working ajax-Calls the SECOND Cookie sent in the Request-Header equals the Set-Cookie property returned by the Response-Header and the first doesnt!
- In non-working calls the FIRST cookie matches and the second doesnt!
- IE(9) doesnt have any problem at all. I found out that he sends every single request using 2 Cookies, not only the ajax ones! The bug described above never appears with IE.
To 1.): I found a Filter in my Sourecode. It implements Java's Filter-Class and is apparently ran through by every request sent to the server. It basically only does one thing, which is called rewriteCookieToHeader. This function checks if (response.containsHeader("SET-COOKIE") ) and if that is true it rewrites that property using the current SessionID and also adding the two flags HttpOnly and Secure
This is what apparently causes the appearance of a second cookie. If i comment this out the bug described does not appear anymore! As well as if i change the if(cond) to if(!cond).
However, i feel like this function has a security-purpose. Its used against some Session-Hijacking apparently, as well as i guess that those two flags are a necessary security measurement.
But it makes no sense at ALL that this function causes the appearance of a second cookie! From the HttpServletResponse documentation it says that : " setting SET-COOKIE when it is already set will cause the old value to be replaced with the new one ".
This and the fact that the new cookie that randomly appears in the requests never equals any of the SET-COOKIE values! It just magically appears and it is mentioned nowhere by the server or the function that apparently causes it in any way!
So on the one side i can remove the bug by removing rewriteCookieToHeader() but on the other side i just dont understand how this function could possibly cause what is causes!
I realise that this is a very specific bug and it goes deep into my implementation.
I just hope that someone might get a hint by what i have described and could suggest some further things that i could test out!
Edit: Here are request and response header-example for working (first two) and non-working (last two) ajax-call.
Working call
REQUEST
Host: localhost:9002
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0
Accept: */ *
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: https://localhost:9002/history.html
Content-Length: 22
Cookie: JSESSIONID=EAB07711A78F1086E0FE55963AD973D3; JSESSIONID=EAB07711A78F1086E0FE55963AD973D3
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
RESPONSE
Content-Encoding: gzip
Content-Language: de
Content-Length: 611
Content-Type: text/html;charset=UTF-8
Date: Mon, 02 Mar 2015 10:05:35 GMT
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=EAB07711A78F1086E0FE55963AD973D3
Non-working call
REQUEST
Host: localhost:9002
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0
Accept: */ *
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: https://localhost:9002/history.html
Content-Length: 22
Cookie: JSESSIONID=705C77CBBE678624BAD25DD97E7D0DF8; JSESSIONID=E67B1E2486D5410CC1A73B30D4E78206
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
RESPONSE
Content-Language: de
Content-Length: 0
Date: Mon, 02 Mar 2015 10:17:14 GMT
Location: https://localhost:9002/login.html
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=705C77CBBE678624BAD25DD97E7D0DF8