Tomcat 8.0.30 Session lost
Hi, I have a very rare problem regarding session handling. It is reproducible only on a single server environment. Of cause this is the productive server. I use container authentication and for simplicity 'tomcat-user.xml'. Login is done via HttpServletRequest.login() method, whenever I need to access user and role information. The HttpServletRequest is saved in a ThreadLocal during request processing. While that normally does the job. There is one servlet that produces simple thumbnails that triggers a problem. Session handling is done via Cookies. A search result page lists several thumbnail images and the browser tries to load them (of cause) in parallel. After the first thumbnail is loaded, the sessionId suddenly changes. As the browser now submitting the "false" sessionId, new sessions are created and the browser gets that new sessionId in the response. The session from the first request is lost at that point and so are the login credentials. Why are sessionIds changing during the request? Here are the logs I produce via a Servlet Filter: - REQUEST - [dev-mir] DEBUG MCRRequestDebugFilter: REQUEST URI: /mir/img/pdfthumb/Document_derivate_0049/2015-05-06_Protokoll%20der%20Sitzung%20des%20Fakult%C3%A4tsrates_%C3%B6ffentlich.pdf Cookies: {path=null, maxAge=-1, domain=null, name=JSESSIONID, comment=null, httpOnly=false, secure=false, class=class javax.servlet.http.Cookie, value=BD12BA0ED4546B5BC119727DAF97086B, version=0} COOKIES END REQUEST PARAMETERS: centerThumb: no, REQUEST PARAMETERS END Session is requested by cookie. Session is not requested by URL. Session is valid. SESSION BD12BA0ED4546B5BC119727DAF97086B created at: 2016-01-07T15:18:51.068 SESSION ATTRIBUTES: mycore.session: {} SESSION ATTRIBUTES END Header: accept: image/png,image/*;q=0.8,*/*;q=0.5 accept-encoding: gzip, deflate accept-language: en-US,en;q=0.5 cache-control: max-age=0 connection: keep-alive cookie: JSESSIONID=BD12BA0ED4546B5BC119727DAF97086B host: cms.example.com:8291 if-modified-since: Wed, 06 Jan 2016 14:40:00 GMT if-none-match: "4e0daa3453247bcfd985ee28de9616de" referer: http://cms.example.com:8291/mir/servlets/solr/select?q=objectType:mods%20AND%20createdby:protokoll=mods.dateIssued%20desc user-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 HEADERS END - RESPONSE - [dev-mir] DEBUG MCRRequestDebugFilter: RESPONSE URI: /mir/img/pdfthumb/Document_derivate_0049/2015-05-06_Protokoll%20der%20Sitzung%20des%20Fakult%C3%A4tsrates_%C3%B6ffentlich.pdf Status: 304 Header: Cache-Control: max-age=31536000 ETag: "4e0daa3453247bcfd985ee28de9616de" Expires: Sun, 24 Jan 2016 15:30:02 GMT Set-Cookie: JSESSIONID=0A88AABC33D336900279B2378CD510B1; Path=/mir/; HttpOnly HEADERS END - NEXT REQUEST - [dev-mir] DEBUG MCRRequestDebugFilter: REQUEST URI: /mir/img/pdfthumb/Document_derivate_0047/2015-03-25_Protokoll%20der%20Sitzung%20des%20Fakult%C3%A4tsrates_%C3%B6ffentlich.pdf Cookies: {path=null, maxAge=-1, domain=null, name=JSESSIONID, comment=null, httpOnly=false, secure=false, class=class javax.servlet.http.Cookie, value=BD12BA0ED4546B5BC119727DAF97086B, version=0} COOKIES END REQUEST PARAMETERS: centerThumb: no, REQUEST PARAMETERS END Session is requested by cookie. Session is not requested by URL. Session is not valid. Header: accept: image/png,image/*;q=0.8,*/*;q=0.5 accept-encoding: gzip, deflate accept-language: en-US,en;q=0.5 cache-control: max-age=0 connection: keep-alive cookie: JSESSIONID=BD12BA0ED4546B5BC119727DAF97086B host: cms.example.com:8291 if-modified-since: Wed, 06 Jan 2016 14:40:02 GMT if-none-match: "9e485dcd85a2b2ee373717a67c282873" referer: http://cms.example.com:8291/mir/servlets/solr/select?q=objectType:mods%20AND%20createdby:protokoll=mods.dateIssued%20desc user-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 HEADERS END [dev-mir] DEBUG MCRServlet: Setting ReqCharEncoding to: UTF-8 [dev-mir] DEBUG MCRHttpSessionListener: HttpSession 20934FB3493889B9EE0FB425A002BB28 is beeing created by: org.apache.catalina.session.StandardSessionFacade@6a75756b - RESPONSE - [dev-mir] DEBUG MCRRequestDebugFilter: RESPONSE URI: /mir/img/pdfthumb/Document_derivate_0047/2015-03-25_Protokoll%20der%20Sitzung%20des%20Fakult%C3%A4tsrates_%C3%B6ffentlich.pdf Status: 304 Header: Cache-Control: max-age=31536000 ETag: "9e485dcd85a2b2ee373717a67c282873" Expires: Sun, 24 Jan 2016 15:30:03 GMT Set-Cookie: JSESSIONID=20934FB3493889B9EE0FB425A002BB28; Path=/mir/; HttpOnly HEADERS END kind regards, Thomas - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
2016-01-08 19:02 GMT+03:00 Christopher Schultz: > Thomas, > > On 1/8/16 8:00 AM, Thomas Scheffler wrote: >> Am 08.01.16 um 11:43 schrieb Olaf Kock: >>> Is there any chance that the first and correctly authenticated cookies >>> (despite the debug output "secure=false") are https-only cookies and >>> won't get transmitted in http, thus triggering new sessions? E.g. any >>> chance they get rewritten at another level (Apache httpd, ServletFilter, >>> others) to be secure only - or that the debug output is slightly >>> incorrect because it omits the secure flag? >> >> This is from a test installation on the productive server where it can >> only be observed. For simplicity I use the maven cargo plugin to setup >> the tomcat here. It shows the same behavior on the productive server, >> where it uses HTTPS in combination with Apache HTTPD. >> >> I use BeanUtil.describe() to produce the cookie String. So this should >> all be correct. >> >> This error comes up on every browser with at least a certain number of >> request to that servlet. It has something to do with a race condition or >> side effect I'm not aware off. >> >> If I do not use container authentication, HTTP sessions won't get lost. >> >> Hunting this bugs for so many weeks now and ran out of ideas. > > Tomcat will change the session identifier when the user authenticates. > If you are creating a session before login, you'll see that the session > id changes when authentication is successful. This is to protect against > session-fixation attacks. > > Can you explain why the changing session id breaks your application? Are > you storing session ids somewhere and just not updating the session id > list when the session id changes? It should be possibly to listen for > that event and update your session id list. Or maybe there's a better > way to accomplish your goal rather than keeping your own session id > list. (I'm guessing you have a session id list because it would best > explain the behavior you are describing here.) FYI, http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionIdListener.html - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Is there any chance that the first and correctly authenticated cookies (despite the debug output "secure=false") are https-only cookies and won't get transmitted in http, thus triggering new sessions? E.g. any chance they get rewritten at another level (Apache httpd, ServletFilter, others) to be secure only - or that the debug output is slightly incorrect because it omits the secure flag? Olaf Am 08.01.2016 um 10:07 schrieb Thomas Scheffler: > Hi, > > I have a very rare problem regarding session handling. It is > reproducible only on a single server environment. Of cause this is the > productive server. > > I use container authentication and for simplicity 'tomcat-user.xml'. > > Login is done via HttpServletRequest.login() method, whenever I need > to access user and role information. The HttpServletRequest is saved > in a ThreadLocal during request processing. > > While that normally does the job. There is one servlet that produces > simple thumbnails that triggers a problem. Session handling is done > via Cookies. > > A search result page lists several thumbnail images and the browser > tries to load them (of cause) in parallel. > > After the first thumbnail is loaded, the sessionId suddenly changes. > As the browser now submitting the "false" sessionId, new sessions are > created and the browser gets that new sessionId in the response. The > session from the first request is lost at that point and so are the > login credentials. > > Why are sessionIds changing during the request? > > > Here are the logs I produce via a Servlet Filter: > > - REQUEST - > > [dev-mir] DEBUG MCRRequestDebugFilter: REQUEST URI: > /mir/img/pdfthumb/Document_derivate_0049/2015-05-06_Protokoll%20der%20Sitzung%20des%20Fakult%C3%A4tsrates_%C3%B6ffentlich.pdf > > Cookies: > {path=null, maxAge=-1, domain=null, name=JSESSIONID, comment=null, > httpOnly=false, secure=false, class=class javax.servlet.http.Cookie, > value=BD12BA0ED4546B5BC119727DAF97086B, version=0} > COOKIES END > > REQUEST PARAMETERS: > centerThumb: no, > REQUEST PARAMETERS END > > Session is requested by cookie. > Session is not requested by URL. > Session is valid. > SESSION BD12BA0ED4546B5BC119727DAF97086B created at: > 2016-01-07T15:18:51.068 > SESSION ATTRIBUTES: > mycore.session: {} > SESSION ATTRIBUTES END > > Header: > accept: image/png,image/*;q=0.8,*/*;q=0.5 > accept-encoding: gzip, deflate > accept-language: en-US,en;q=0.5 > cache-control: max-age=0 > connection: keep-alive > cookie: JSESSIONID=BD12BA0ED4546B5BC119727DAF97086B > host: cms.example.com:8291 > if-modified-since: Wed, 06 Jan 2016 14:40:00 GMT > if-none-match: "4e0daa3453247bcfd985ee28de9616de" > referer: > http://cms.example.com:8291/mir/servlets/solr/select?q=objectType:mods%20AND%20createdby:protokoll=mods.dateIssued%20desc > user-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 > Firefox/38.0 > HEADERS END > > - RESPONSE - > > [dev-mir] DEBUG MCRRequestDebugFilter: RESPONSE URI: > /mir/img/pdfthumb/Document_derivate_0049/2015-05-06_Protokoll%20der%20Sitzung%20des%20Fakult%C3%A4tsrates_%C3%B6ffentlich.pdf > > Status: 304 > Header: > Cache-Control: max-age=31536000 > ETag: "4e0daa3453247bcfd985ee28de9616de" > Expires: Sun, 24 Jan 2016 15:30:02 GMT > Set-Cookie: JSESSIONID=0A88AABC33D336900279B2378CD510B1; Path=/mir/; > HttpOnly > HEADERS END > > > - NEXT REQUEST - > > [dev-mir] DEBUG MCRRequestDebugFilter: REQUEST URI: > /mir/img/pdfthumb/Document_derivate_0047/2015-03-25_Protokoll%20der%20Sitzung%20des%20Fakult%C3%A4tsrates_%C3%B6ffentlich.pdf > > Cookies: > {path=null, maxAge=-1, domain=null, name=JSESSIONID, comment=null, > httpOnly=false, secure=false, class=class javax.servlet.http.Cookie, > value=BD12BA0ED4546B5BC119727DAF97086B, version=0} > COOKIES END > > REQUEST PARAMETERS: > centerThumb: no, > REQUEST PARAMETERS END > > Session is requested by cookie. > Session is not requested by URL. > Session is not valid. > Header: > accept: image/png,image/*;q=0.8,*/*;q=0.5 > accept-encoding: gzip, deflate > accept-language: en-US,en;q=0.5 > cache-control: max-age=0 > connection: keep-alive > cookie: JSESSIONID=BD12BA0ED4546B5BC119727DAF97086B > host: cms.example.com:8291 > if-modified-since: Wed, 06 Jan 2016 14:40:02 GMT > if-none-match: "9e485dcd85a2b2ee373717a67c282873" > referer: > http://cms.example.com:8291/mir/servlets/solr/select?q=objectType:mods%20AND%20createdby:protokoll=mods.dateIssued%20desc > user-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 > Firefox/38.0 > HEADERS END > > > > > [dev-mir] DEBUG MCRServlet: Setting ReqCharEncoding to: UTF-8 > [dev-mir] DEBUG MCRHttpSessionListener: HttpSession > 20934FB3493889B9EE0FB425A002BB28 is beeing created by: > org.apache.catalina.session.StandardSessionFacade@6a75756b > > - RESPONSE - > > [dev-mir] DEBUG MCRRequestDebugFilter: RESPONSE URI: >
Re: Tomcat 8.0.30 Session lost
Am 08.01.16 um 11:43 schrieb Olaf Kock: Is there any chance that the first and correctly authenticated cookies (despite the debug output "secure=false") are https-only cookies and won't get transmitted in http, thus triggering new sessions? E.g. any chance they get rewritten at another level (Apache httpd, ServletFilter, others) to be secure only - or that the debug output is slightly incorrect because it omits the secure flag? This is from a test installation on the productive server where it can only be observed. For simplicity I use the maven cargo plugin to setup the tomcat here. It shows the same behavior on the productive server, where it uses HTTPS in combination with Apache HTTPD. I use BeanUtil.describe() to produce the cookie String. So this should all be correct. This error comes up on every browser with at least a certain number of request to that servlet. It has something to do with a race condition or side effect I'm not aware off. If I do not use container authentication, HTTP sessions won't get lost. Hunting this bugs for so many weeks now and ran out of ideas. regards, Thomas - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Am 08.01.16 um 14:03 schrieb André Warnier (tomcat): Hi Thomas. It is a bit difficult to figure out where the problem really is, without having the full picture of what is going on (your web.xml configuration, the order and precise timing in which requests really happen etc.). But one thing I would really focus on, is the general overall logic of the application, to see if the order in which things happen is really consistent with the authentication method that you are using. For example, if the initial call to the first page (the one which contains the document links) does not immediately trigger a session authentication, and in the meantime the browser starts making multiple quasi-simultaneous requests for the links present in that page, then things would get out of sync, since when the authentication does happen, the session-id /will/ change (check Wikipedia for "web session fixation"). That would overwrite the session-id cookie, perhaps in the middle of the calls still being made to retrieve the document links mentioned in the page. Hi André, I would like to give some insight information on how authentication is handled. As the application can run in command line or as a web application we have a custom session handling (refer to it as 'core session'). Within the core session there is a UserInformation implementation attached. UserInformation can have different implementations and allows to ask for the user id and if the user in in a specific role. In the HttpSession we only store the sessionId of our core session. When the http session is destroyed we also close the core session. So there is only this one property "mycore.session" in the httpsession. When using servlet container authentication (error happens only with it). I need to access the request object which is stored in a ThreadLocal and released at end of the request. Here are the most important methods private void loginIfNeeded() { //getCurrentRequest() returns Optional getCurrentRequest().ifPresent(currentRequest -> { if (currentRequest.getUserPrincipal() == null) { try { currentRequest.login(user, pwd); LOGGER.debug("Re-Logged in: " + user); } catch (ServletException e) { throw new RuntimeException(e); } } }); } public String getUserID() { loginIfNeeded(); lastUser = getCurrentRequest() .flatMap(r -> Optional.ofNullable(r.getUserPrincipal())) .map(Principal::getName) .orElseGet(() -> Optional.ofNullable(lastUser) .orElseGet("guest"); return lastUser; } public boolean isUserInRole(String role) { loginIfNeeded(); return getCurrentRequest().map(r -> r.isUserInRole(role)).orElse(Boolean.FALSE); } When the user first authenticated with his login credentials we put the servlet container user information to the core session. As the HTTP session is linked to it, we just need the http session to keep track of it. The error happens to be later, (possibly) many requests after the login form that put UserInformation to the core session. So there is no racing condition at that position. You can see in the code that I need to re-login from time to time, as the request object does not always return the remote user. Why does that change the sessionId? How can I track the user than? IMHO if HttpServletRequest.login() should only be called once in a http session than getUserPrincipal() should always return a user after login() is called on one request regarding to the same session, or? But if calling login() always invalidates the old session we have a problem here. As long as request are coming in sequentially this would be OK, as the browser gets a new cookie value with every response. But browsers are out of control and want to give cpu cores a good time. Anyway. I hope you are not lost in the details and are still willing to help me. regards, Thomas - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
On 08.01.2016 10:07, Thomas Scheffler wrote: Hi, I have a very rare problem regarding session handling. It is reproducible only on a single server environment. Of cause this is the productive server. I use container authentication and for simplicity 'tomcat-user.xml'. Login is done via HttpServletRequest.login() method, whenever I need to access user and role information. The HttpServletRequest is saved in a ThreadLocal during request processing. While that normally does the job. There is one servlet that produces simple thumbnails that triggers a problem. Session handling is done via Cookies. A search result page lists several thumbnail images and the browser tries to load them (of cause) in parallel. After the first thumbnail is loaded, the sessionId suddenly changes. As the browser now submitting the "false" sessionId, new sessions are created and the browser gets that new sessionId in the response. The session from the first request is lost at that point and so are the login credentials. Why are sessionIds changing during the request? Here are the logs I produce via a Servlet Filter: [snip] Hi Thomas. It is a bit difficult to figure out where the problem really is, without having the full picture of what is going on (your web.xml configuration, the order and precise timing in which requests really happen etc.). But one thing I would really focus on, is the general overall logic of the application, to see if the order in which things happen is really consistent with the authentication method that you are using. For example, if the initial call to the first page (the one which contains the document links) does not immediately trigger a session authentication, and in the meantime the browser starts making multiple quasi-simultaneous requests for the links present in that page, then things would get out of sync, since when the authentication does happen, the session-id /will/ change (check Wikipedia for "web session fixation"). That would overwrite the session-id cookie, perhaps in the middle of the calls still being made to retrieve the document links mentioned in the page. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Thomas, On 1/8/16 8:00 AM, Thomas Scheffler wrote: > Am 08.01.16 um 11:43 schrieb Olaf Kock: >> Is there any chance that the first and correctly authenticated cookies >> (despite the debug output "secure=false") are https-only cookies and >> won't get transmitted in http, thus triggering new sessions? E.g. any >> chance they get rewritten at another level (Apache httpd, ServletFilter, >> others) to be secure only - or that the debug output is slightly >> incorrect because it omits the secure flag? > > This is from a test installation on the productive server where it can > only be observed. For simplicity I use the maven cargo plugin to setup > the tomcat here. It shows the same behavior on the productive server, > where it uses HTTPS in combination with Apache HTTPD. > > I use BeanUtil.describe() to produce the cookie String. So this should > all be correct. > > This error comes up on every browser with at least a certain number of > request to that servlet. It has something to do with a race condition or > side effect I'm not aware off. > > If I do not use container authentication, HTTP sessions won't get lost. > > Hunting this bugs for so many weeks now and ran out of ideas. Tomcat will change the session identifier when the user authenticates. If you are creating a session before login, you'll see that the session id changes when authentication is successful. This is to protect against session-fixation attacks. Can you explain why the changing session id breaks your application? Are you storing session ids somewhere and just not updating the session id list when the session id changes? It should be possibly to listen for that event and update your session id list. Or maybe there's a better way to accomplish your goal rather than keeping your own session id list. (I'm guessing you have a session id list because it would best explain the behavior you are describing here.) -chris - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org