My Restful service application developed with Spring 3 is deployed on Tomcat7. I use a chrome app called Postman to request REST services.
I have a custom-filter placed before all the services (except the non-secured service login) for checking Session and application specific cookies.
This filter returns HTTP status:403 if cookies are not present or invalid in the incoming HttpServletRequest. The filter (myCustomSecurityFilter) is Singleton scoped.
<security:intercept-url pattern="/services/v1/login" access="permitAll()" /> <security:custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="myCustomSecurityFilter" />
I observed that in a speicific case old HttpServletRequest is used. Please see the following scenario
Case #1: All requests are over HTTPS.
All cookies are removed and browser is restarted.
Call HTTPS serveice: ..\services\v1\account. As this service has to be called after ..\services\v1\login, 403 response is expected. Actual response :403.
A new session is created and a JSESSIONID is returned by Tomcat. Say, JSESSIONID_1.
Request ..\services\v1\login . Expected and Actual respose 200-OK.
A new session is created and a JSESSIONID is returned by Tomcat. Say, JSESSIONID_2.
Also application specific cookies are returned to client/browser. Say, App_cookie_1.
Call any other service other than ..\services\v1\account. All are successful(200).
Cookies JSESSIONID_2, App_cookie_1 are sent by request and the same can be observed after receiveing response.
Note: This step is not important. Step 5 can be reproduced with or without this step.
Request ..\services\v1\account. Expected: 200. Actual: 403.
When I debugged the HttpServletRequest received by the doFilter method in my SecurityFilter mentioned above, I see that the HttpServletRequest contains old cookies of the previous request to the same service ..\services\v1\account.
i.e JSESSIONID_1. No app cookie.
I checked cookies with the help of httpServletRequest.getCookies()
Browser shows Cookies JSESSIONID_2, App_cookie_1. I am sure that Tomcat receieves Cookies JSESSIONID_2, App_cookie_1 becasue I have access logging enabled.
So, it is Spring (my code or config on top of the the Spring framework) passing old HttpServletRequest to filter. But how? why?
Request ..\services\v1\account. Expected: 200. Actual: 200.
Cookies JSESSIONID_2, App_cookie_1 are sent by request and the same can be observed after receiveing response.
So, old cookies are used only once and that too only for the same service in this case (..\services\v1\account).
Webapp works as expected in the following cases (above steps are denoted by numbers):
Case2: 1,2,3,4,5,6. All are HTTPS requests except #2 (login request). #5 returns 200 if #2 is a HTTP request!! This is also a surprise.
Case3: 2,3,4,5,6.
Case4: 2,3,5,6.
Step 4 is not important. Step 5 can be reproduced with or without this step. I placed this to explain that previous request of the same service is loaded and no effect on other services.
Problem is definitely not with ..\services\v1\account. Because I just used this service for example. Case 1 can be repeated with any secured service in the application.
I tried managing my session with newSessio, migrateSession options.
<security:session-management session-fixation-protection="newSession">
<security:concurrency-control max-sessions="1" />
</security:session-management>
Thanks for reading my question. It would be great if you could give some pointers.
Please let me know if I am not clear.
(answering as I faced a similar problem recently. Even though the question is too old)
..\services\v1\login
A new session is created and a JSESSIONID is returned by Tomcat.
How is the session created here?
Assuming its typically created like below
HttpServletRequest.getSession(true);
there is a high chance server gets an old session here.
Can you try a
session.Invalidate()
or
request.logout()
So that any open session is invalidated.after that you try creating the session again
HttpServletRequest.getSession(true);
Related
Cookies support - Problem?
Original Issue/Background:
We have API based on servlet / JSON running in Openshift, the web server used in openshift is Tomcat.
We store information to httpsession and everything works fine when used directly against openshift / tomcat (POST / GET). But when we configured apigee against existing methods the session is lost. Stuff is stored correctly in the session in server side, but when second request comes from apigee into the tomcat the session is "lost"
Piece of java code to get the session is plain httpsession.getRequest(). As said this works fine when using backend directly. Is there some additional steps (cookies etc) needed to maintain the session when requests are used through apigee?
Update Findings;
With short debug an traffic monitoring the reason of the error in apigee is confirmed to be that it does not pass JSessionId to requests. This means that cookies support should be enabled somehow in the API proxy settings / Configuration.
Anyone have an idea where or if this can be resolved?
First off, cookies aren't part of a proper RESTful payload -- if you grabbed the headers you could store them with an access_token as part of the generate token policies.
That aside, you should be able to pass the cookies back to the requesting App and then let the app pass them back to the API -- my jokeindex API lets you do this.
Make sure you don't have any AssignMessage policies in the flow that are stripping out the headers accidentally -- something like this:
<Set>
<Headers />
</Set>
as that will remove ALL headers. Also, you can look at the Trace tool in Apigee to check each policy step along the way to see if you're stripping the Cookie: header from the requesting payload.
When you have your resource on address "http://yourdomain.com/somewhere/", and you redirect to that resource from apigee API, for instance by url: http://yourapi.apigee.net/v0/myresource" what you get back from your server is cookie for /somewhere/ not v0/resource/somewhere, so basically when browser gets cookie back, it does not put it into correct place and discards it. At least that was/is my case.
You should ping #bissell about this but I did find this article that might be helpful:
http://community.apigee.com/groups/learn-create-and-manage-apis/some-basic-questions-new
Also, you might be able to fix your issue by adding an "extract variable" policy to the request that captures the JSessionId and then adding an "assign message" policy to add it back to the request.
You can assign policies from API Platform>Dashboard>API Proxies>YOUR API>Develop
I'm trying to do a simple load-test in a website which requires you to log in first.
I read the jmeter documentation about the cookie manager and looks like as long as I make all my requests within the same thread group where the cookie manager is the sessionID is shared among the http requests but is not my case.
The simple structure I have is:
Thread Group
HTTP Cookie Manager
HTTP Requests Defaults
Simple Controller
http request // POST method to authenticate in the site (this works fine, I get a session id)
http request // GET method (this one should use the same session id from the previous http requests but I get a new one instead)
I did this same web page flow in firefox using firebug to see the requests/responses and the session id is the same, the server doesn't send a new one so looks like the cookie manager is not keeping the same session id and using it for all the requests.
Can someone point me in the right direction? What I am doing wrong?
Check the get request sends the same jsessionid cookie in the request as the one returned in previous response.
If it's the case then check your login was fine, as it is probably root cause of issue
I have very simple question with request and session in web. When I requested a same page page for multiple time from same browser with different tabs or through new window, session ID and session creation time was same.
This I have done from internet explorer. But when in use a different browser like google chrome and access the same page then different session id and session creation time was there. As far as my understanding says http request is stateless.
So, in my case it does not seem to be stateless within same browser as for different http request new thread is created by creating new servlet by container. So I have come to following conclusion:
If request is send from same browser with different tabs opened or through another new window at that time, the request always use the same thread for servlet operation with same session Id. If request is send from different browser then new http request is sent with new session ID.So,my question is then when it is stateless? If the request is send concurrently from different browser? If i declare scope="request"> and scope="session"> in spring then it also follows the same case ? If I am wrong in my understanding please correct me.
Spring
scope="request"
Creates new instance of bean per request.
scope="session"
Creates new instance of bean per session.And maintains instance of bean throughout the session life-cycle
Refer this for better understanding
Irrespective of browsers, Http protocol is stateless. State-fullness is implemented via cookies and session.
When request is sent from the browser, servers creates session and sends back a unique id to the client. And the client uses this id(Cookie) in subsequent request so that server could identify request and associate it with the session.
As far as requests are concerned, server creates separate thread to handle each request irrespective of window, tab or browser. However there will be only one session created per browser.
Note: Latest browsers share the session and the request made from tab, or new window will use the same session. Ex latest IE releases IE7, IE8 and IE9 are well know as Loosely-Coupled IE (LCIE). check this for more details LCIE
When your server application starts a new session, the servlet container sends a Set-Cookie header with a JSESSIONID back to the browser. The browser saves that cookie, and sends it back to the server with each request regardless of what tab you are making the request from. Obvoiusly other browsers don't have access to that cookie, so they will receive another one from the server.
When your server receives a request with a JSESSIONID cookie, it can correlate that request with requests with the same id made earlier. The serlvet container is able to associate different attributes with that id, and persist these attributes between requests. The http session object is basically a container for these attributes, to which your server application has a read/write access. Basically this is how statefullness is implemented with http sessions on top of the otherwise stateless http protocol.
As for the threads: each request can be processed by any random thread, because the session data is not bound to a particular thread. It is the servlet container that maintains the mapping from session id to the session object containing the different attributes. Consequently any random thread can access the session object belonging to the current request based on its session id.
In Spring, request scope means that a bean instance gets newly created for each request, while the lifecycle of the session scoped beans is bound to that of the http session.
I am working on this problem for 2 days now and I am hoping that anyone here had a similar problem and a solution for that.
The problem:
It's a Spring MVC (2.5.6.) Web Application, which runs in Tomcat 6.
When the start page is requested it redirects the customer to a JSP Page (by using HTML's meta refresh tags) which loads it's content with a lot of Ajax requests (Framework: Prototype). The problem is that Tomcat creates a new session for every AJAX requests (about 67 sessions).
My first thought was that the Session Cookie is stored after the start page is loaded and the Ajax requests forces the Tomcat to create a new session. My approach was to create the session cookie by hand, but this did not make any difference.
The funny thing is that it works in some other tomcat instances, but not in the desired environment for the integration tests. In my opinion it's a Tomcat configuration issue.
After further investigation with Firebug, I found out that Tomcat creates a new Session for every request even if the right JSESSIONID is transfered to it (50B5EA0BCFE811C744CE9C1F9EDE0097):
Request Header 1:
Cookie JSESSIONID=F3206CBF2C961E125821FF22FA31A02D
Response Header 1:
Set-Cookie JSESSIONID=49E000B4D6880F4F94531AB9C78DB667; Path=/JOCA-Music-Portal JSESSIONID=50B5EA0BCFE811C744CE9C1F9EDE0097; Path=/JOCA-Music-Portal
Request Header 2:
Cookie JSESSIONID=50B5EA0BCFE811C744CE9C1F9EDE0097
Response Header 2:
Set-Cookie JSESSIONID=DCCA2D1B98D11223A6B8855800276E27; Path=/JOCA-Music-Portal
UPDATE: Further investigation isolated the problem to the Tomcat Realm configuration. We use a JDBC Realm for login. When the login is deativated, only one Session is created.
If it's activated, Tomcat creates invalidated/expired sessions, that's why a new session is created with each request. But why does Tomcat behave like this?
I'm really desperate, so any thought/hint/solution is well appreciated.
Thank you very much
You can try to analyze the HTTP traffic between your client and your server. Make sure the Cookie header is set correctly in the request and the response.
If using Firefox, you can try to debug with Firebug.
We recently ran into the same issue with an app we were developing. Come to find out, the issue is that Tomcat was modified to help prevent session fixation attacks. By default, a new session id is created on authentication. This started with 6.0.21. Check out the context configuration option 'changeSessionIdOnAuthentication' (tomcat bug/issue is https://issues.apache.org/bugzilla/show_bug.cgi?id=45255).
We ran into the same problem, but when using custom EXTERNALSSO authentication. The solution was to explicitly turn it off in the constructor of our class that inherits from org.apache.catalina.authenticator.AuthenticatorBase:
super.setChangeSessionIdOnAuthentication(false);
I have developed a simple web-app with 2 servlets A and B.
I have a few doubts related to session management for the web-app by Tomcat.
NOTE - I have disabled cookies in my web-browser (Chrome) while accessing the web-app.
1.) When the web-app is first hit, Servlet A gets invoked. Servlet A accesses the session from the request and does a simple sysout of the session hashcode. It then does a sendRedirect to servlet B.
[According to my understanding, since this is the first request, Tomcat will send a cookie containing the new session ID back to the browser. However, since we have not "encoded" the redirect URL using HttpResponse.encodeRedirectURL(), the redirect URL will not contain the session ID appended to it. Please correct me if I am wrong here.]
2.) Since cookies are disabled in my browser, it'll ignore the session ID sent back in the cookie and issue a new request to the redirect URL (which also does not have the session ID appended to it).
3.) The new request causes servlet B to be invoked, whoch also accesses the request session and does a sysout of the session hashcode.
What perplexes me is that both Servlets A and B output the same session hashcode, which means that they get the same session from both requests.
How does the second request from the browser map to the same session as before, even though no session ID has been sent ?
Thanks !
There are only 2 ways to pass sessions between requests: Cookie and URL rewrite. If you don't see the session ID in the URL, it must be cookies.
Are you sure the cookie is disabled? It should be easy to see from a HTTP header trace.
Are you certain you've disabled "in memory" cookies? Often browsers will let you disable persistent cookies which are saved to disk, but they'll still allow the transient in memory cookies which only stay resident during a browser session.
I recommend Wireshark for analyzing the HTTP stream. That way you can see the cookies that are sent and received by your browser.
This is strange.
When I tested the application yesterday, it was exhibiting a behaviour similar to what I have described. However, as I test the application now, it behaves perfectly, as I expect it to.
The cause could probably be that I did not restart my browser session after disabling cookies.
Will let you guys know if I experience the same behaviour again.
Thanks for your time guys !