IWS is a desktop application with its own webBrowser component to call Scripting web-app when needed. Scripting is located in a Tomcat6.
Scripting is basically an JSP application. (Really it is an engine who builds an JSP application from the human actions over its graphical interface, like define flows, buttons, content, etc, but I am talking about the "Script" it generates as an JSP)
I need to hack Scripting so it can share space (via frames) in that webBrowser component of IWS application.
The IWS call 2 times to start.jsp:
the first time, in a hidden way (probably a direct http query from IWS code), without any special parameters. The original start.jsp do 2 302 (so the call visits 3 pages total) it ends using the jsesionId both in cookie and as a parameter (but not at the last 302)
second time, with the jSessionId and a bunch of important parameters. It only uses the jSessionId as the parameter. As far as I have seen in fiddler, no cookie is used when it works correctly as jsessionId is inside its own
So I guess that the first time ìt is just to get a new jSessionId.
The solution I am trying now is to replace Scripting starting page with a new frames page which, in one of the two frames it holds, it loads the web aplication, and another application in the second frame. Depending on data from the first frame it will update the second frame.
So something like to:
we had start.jsp... (really it is called something different)
and we end with:
start.app.jsp (which is original start.jsp, just renamed)
start.jsp (is the new including html which wraps the previous start.jsp)
The new start.jsp uses its own url, changing start.jsp into start.app.jsp, to invoke the true Scripting application inside an iframe.
But I have been suffering from like session problems. I am not an expert in tomcat. I learned that it controls the session with cookies or with parameters. I think it is configured to work with the URL sessionId but I am not really sure. I have set META-INF/settings.xml to disable cookie use in sessions, but it still show the cookie in the cookies list.
My problem is that in that second time start.jsp is called, it appear than somethink like an "old cookie" is being used, ignoring the jsessionId from the URL. Some weird errors appear at WWG00000E: WWGAIL - Error: ID was not provided for function getInteractionKVPair Detail:
It is like it is returning to an old cookie with another jsessionid. That 'old' jsessionid is the same each time the error shows up.
Sniffing with fiddler, I see that the second start.jsp starts with the right jsessionId in the URL, but its cookies are like from another session, and it stops to add the jsession id with each redirection since this happens. It is like it is executing in a completely different universe. Is this normal?????
Currently I am trying without avail to force the cookie jSessionId and also the links so they include the jSessionId.
Please, do you have any idea?
Thanks!
Edited2: if I place it without frames (restoring default start.jsp). At IWS works only the first time (interaction), while in any subsequent one the problem start to appear...
Ok, solved at last...
At least with this version of Tomcat:
A call to a jsp without jSessionId creates a new jSessionId in your app cookie.
Any further on in time html request will use the cookie jSessionId instead of the one present on the URL, so you lose any type of multisession support.
It is something special than in a webBrowser component, doing a two steps connections, the first request never have an associated cookie, so it works OK, giving you a cookie with a new jSessionId, and then you can do a new, cookieless, second request which uses the jSessionId of the URL and have not cookie or have "a default" cookie without jSessionId. When this webBrowser requests a jsp page without jSessionId in its URL, as said, the problem starts, so if the first request includes a non jSessionIded call, Tomcat gives you a jSessionId which is set on your "default app cookie", so the second request ignores any URL jSessionId to use the one on that cookie.
In a web browser, I have observed that in at least firefox, cleaning the cookies is not enough to eliminate this "default cookie". But maybe it could be the classic "It takes too long so you think it is clean but really it is not". Not sure.
I know this sounds confusing. I have not the time to do further testing about this.
As far as I have understood, it is like, when it works OK, it is working like with an "session cookie" (without jSessionId), while when it does not work it takes the "default cookie" (with jSessionId) and starts ignoring URL jSessionId.
I have sent an email to the dev mailinglist of Tomcat. (One said that the correct place was the user mailinglist... but here you are ;-) )
Related
While upgrading some legacy code from Wicket 1.5 to Wicket 9, I found that redirection to a "Session expired" notification page seems to be partially broken.
I have the following statement, which always used to work before, in the main application file:
getApplicationSettings().setPageExpiredErrorPage(MyErrorPage.class);
Here is the scenario which should trigger redirection to "MyErrorPage":
The user successfully logs in and goes into any menu option.
They sit around for a while, doing nothing, and their session times out.
After this period of inactivity, they click on a link or attempt to submit a form.
At this point, they ought to be redirected to "MyErrorPage".
The menu option invoked in point (1) - lets call it MyMenuPage - could have been invoked with two possible types of syntax:
Either:
setResponsePage(MyMenuPage.class);
Or:
setResponsePage(new MyMenuPage(params));
It seems that the user will only be redirected to my custom error page if the original menu page was invoked with the SECOND syntax.
If the original page was invoked with the FIRST syntax, the user is sent straight to the login page, without any explanation about the fact that their page has expired.
Please can someone advise me how to get the same result in both types of page - which are not stateless, because the user has logged in.
There is a difference between page being expired and http session expiration.
As PageExpiredException's javadoc [I] explains there are three possible reasons for it:
the page have never been stored there, e.g. an error occurred during the storing process
the http session has expired and thus all pages related to this session are erased too
the page instance has been erased because the store size is exceeded
Wicket stores all stateful pages on the disk. Later when you use such page, e.g. by clicking a link, Wicket loads the page instance, executes the click, and render the response.
If the http session is expired then most probably your authentication strategy kicks in and redirects to the login page without even trying to load the old page. If you use Component#continueToOriginalDestination() after successful login then the user will be navigated to a new instance of the old page.
To summarize:
if the http session expires then your application redirect to the LoginPage
if a page instance is expired then by default Wicket will create a new instance of it (see PageSettings#setRecreateBookmarkablePagesAfterExpiry(boolean)) or show the configured getApplicationSettings().setPageExpiredErrorPage(MyPage.class); will be rendered
To debug what happens in your case put some breakpoints at the following places:
https://github.com/apache/wicket/blob/6a7e4c3d770324f125fbf43615c7708b67c8d8c5/wicket-core/src/main/java/org/apache/wicket/Component.java#L1061
https://github.com/apache/wicket/blob/6a7e4c3d770324f125fbf43615c7708b67c8d8c5/wicket-auth-roles/src/main/java/org/apache/wicket/authroles/authentication/AuthenticatedWebApplication.java#L134
I. https://github.com/apache/wicket/blob/master/wicket-core/src/main/java/org/apache/wicket/protocol/http/PageExpiredException.java#L31
Seems like I just have to work round this by always using the following syntax:
setResponsePage(new MyPage());
This is not the end of the world, because at least I don't have to pass any parameters in, in order to trigger the required "Go to session expired page" behaviour.
I have a java web application. I implemented a login system, with user rights a while ago, and included a "remember-me" functionality with unique string ID's saved client side in cookies.
This has worked ok, except for the fact that the remember me functionality always fails on first page load whenever a new session starts. However, since most users access a non-restricted page first, complaints has been absent. Nonetheless, I'd like to fix it. Here is what I have learned.
I use implementations of javax.servlet.Filter to check if a user has rights to se a page. for example baseURL/pages/admin/*. Filter interface has a method called doFilter, which accepts a ServletRequest, and ServletResponse object as parameters. I cast these to HttpServletRequest and HttpServletResponse. The HttpServletRequest gives me access to cookies and session.
If i iterate through the cookies, I find my "remember"-cookie, with the unique ID as a value. However, this ID is wrong.
Now, in my Servlet class, which follows the front controller pattern, I also have a check for user logged in, and remember me. But because this is executed after the filter, it is not sufficient to check only here. Still, I do want to check for every page, even if it is not restricted, as it changes the layout slightly if you are logged in.
The java HttpServlet service method accepts a HttpServletRequest and HttpServletResponse object. In other words, no need for casting here. Funny thing is though, If i try to access my cookies from here, it will give me an identical id for the session cookie, but a completely different uid for my "remember"-cookie.
I have found that my system adds new remember cookies for each of my filters. And if I try to access a page in the admin path, both cookies from /webapp/pages, and cookie from /webapp/pages/admin will be present in chrome inspector. When accessing the cookies in the filter, the /webapp/pages/admin is the only one that will exist. Oppositely, the /webapp/pages is the only one that will exist in the front controller servlet service method.
I guess this is because of the mapping of said filter and servlet, which matches the path of the cookie. The problem is that I never intended there to be cookies stored hierarchically, and only want the one to be stored, at /webapp/pages. My system has now stored plenty of these deeper pathed cookies all over my client network, and whenever a user logs in and out, they might get out of sync with a new uid.
Is there a way I can force retrieving the /webapp/pages cookie over the /webapp/pages/admin cookie? Or is there a way to retrieve both? I could just check both uid's for a match if I can manage that (hence the title of my question)
For the future, I have made sure to set the path of cookie storage, so that the same path will be used, but as the cookies has a year to expire, this will not solve my problems for a long time, unless I find a way to check the correct cookie.
The answer to the title question is; you can't.
The browser will decide which cookies it deems most relevant, and there is nothing you can do to change that. When your filter is mapped to a subpath, and servlet is mapped to a higher path, you will get the best matching cookie for each path.
The specific problem in the question text is caused by a bad coding pattern. The remember me cookies should be stored at a specific path when created, in this case /webapp/pages. This will prevent the cookie from being created as multiples, in hierarchical paths.
There is still the problem of already existing cookies client side. These can be handled by adding the following javascript in a central area of your code, somewhere where you'd know that all users will encounter it:
document.cookie = 'remember=; path=/webapp/pages/user; expires=' + new Date(0).toUTCString();
document.cookie = 'remember=; path=/webapp/pages/admin; expires=' + new Date(0).toUTCString();
This will set the unwanted cookies to expire at an already past date, effectively deleting it.
Now only one cookie with name "remember" will exist for the domain, and both servlet and filters will fetch the same cookie, regardless of their mapped subpaths.
HI,
This question is from previously answered question by BalusC. The excerpt of the answer as follows:
This happens only if under the covers
a forward by
RequestDispatcher#forward() takes
place. In a forward, the
servletcontainer basically reuses the
same HTTP request/response for a view
(JSP/XHTML page). It does not
force/instruct the webbrowser to send
a brand new request.
What this means is every new view is rendered using the forward. The following are my questions:
If the above is the case, then all the views displayed with the same request?. Because, we are always seeing the same URL in the address bar.
Is it that the values in the previous request is retained for the new request?
In this case, if every request is same then is it like storing in the session, for long time. I am bit confused on the view handling by JSF. Want to understand more internal work flow of JSF.
When we use the <redirect/> in faces-config.xml, will the URL in address bar get changed?
If the above is the case, then all the views displayed with the same request?. Because, we are always seeing the same URL in the address bar.
If it concerns a HTTP POST request and the JSF bean action navigates to a different view, then per saldo you will indeed have two different views in the same request. One for the initial view which is been used to gather/convert/validate the necessary request parameters and update the model values and other for the result view which is been used to show some result.
Is it that the values in the previous request is retained for the new request?
In a forward there's no means of a new request. It's the same request.
In this case, if every request is same then is it like storing in the session, for long time. I am bit confused on the view handling by JSF. Want to understand more internal work flow of JSF.
This is definitely not the case. As to your confusion, it may help to put JSF aside for a while and go playing with plain vanilla JSP/Servlet (which is what JSF is using under the covers). I think the following links may help in getting new insights about how basic JSP/Servlet works and how the average MVC framework on top of JSP/Servlet works:
Servlets tag info page
Design patterns Java web applications
When we use the <redirect/> in faces-config.xml, will the URL in address bar get changed?
Yes. A HTTP redirect sends a HTTP location: newpage.jsf header which in turn instructs the webbrowser to fire a new HTTP GET request on the given location. This get reflected in the browser address bar. You may want to install a HTTP debugging tool like Firebug or Fiddler2 to track HTTP traffic. You'll see that a forward happens inside the same request and a redirect comes with a new request.
If the above is the case, then all the views displayed with the same request?. Because, we are always seeing the same URL in the address bar.
if the url is the same in the web-browser then there can be two cases. either the same request is being forwarded as he mentioned OR new GET request is issued with same URL [which is lesser the case]
Is it that the values in the previous request is retained for the new request?
request life cycle will be from request to response. so after response all the managed bean with request scoped will get destroyed.
When we use the in faces-config.xml, will the URL in address bar get changed?
Yes it will instruct browser to issue new GET request for new URL.
Is it possible to prevent user from opening JSF page in more than one browser tab or window?
I agree with the accepted solution, but if you still have to do it, these steps worked for me (pseudo code/pseudo python):
On the JS side:
if tabId not set:
. generate random number
. set property in sessionStorage
otherwise:
. get it from sessionStorage
make an ajax callback and send tabId
onError:
. alert();
. close current tab (if possible);
. logout
Backend:(JSF):
Create custom filter:
if request contains the tabId info:
if it matches session's tabId: (being tabId not null)
sent response status code to an error such as forbidden
Optionally invalidate session
otherwise apply session filtering (do nothing)
#BalusC The problem concerns old JSF application that is entirely stateful. Why try to figure out some way to inform users that openning the app in two separate tabs is potentially dangerous. In no way can we change session managed beans to request managed beans.
Make all those beans request scoped, install Tomahawk, add <t:saveState value="#{bean}" /> for every bean to every view of which you'd like to retain exactly the same bean state in the subsequent request. This works independently across tabs/windows.
Without Tomahawk, the alternative would be adding <h:inputHidden /> for every bean property which you'd like to retain in the subsequent request. I can however imagine that this may produce nasty boilerplate code when there are much or when they aren't of the standard EL types (for which you have thus to create a Converter). But that's what you get paid for.
One scenario I have in mind:
Put a javascript component in the page that will constantly sending heartbeat to the server via AJAX. As long as there are heartbeat sent from browser, this page will be flagged as 'currently_viewing'. And as long as a page have that flag on, other requests to that page should be rejected.
The detail may be a lot messier than this simple story (e.g. you might need to have some sort of 'page id' to be sent with the heartbeat), but you get the idea (... i hope :).
Everything is possible as long as you are willing to pay the price.
it seems that the Parameter-Name in the GET request, that represents the SessionID (like jsessionid=XXXXXXXXXXXXXXXXXXXXXXXXXX in Tomcat) is not standardized in the servlet-spec? How can I get the (Servelt Container Specific) name of the SessionID? (At least in Websphere there seems to be the possibilty to change the name of the SessionID-Parameter-Name)
=> The underlaying problem is, I need to encode a URL in a servlet ALWYAS with the session ID. But it seems that the "response.encodeURL()" Method only does this if Cookies are disabled (=>therefor using URL-Rewriting with the sessionID in the URL).
What would be an alternative to always encode a URL with a session ID in a servlet? As the first question implies I wanted to build the sessionid on my own but I therefore need the sessionID-Parameter Name that however seems not be be standardized, so I somehow need to get the Parameter-Name from somewhere...)
UPDATE:
The intention is to keep the SessionManagement Functionality provided by the Servlet-Container and not turn it off completely. I need to pass a Callback URL to a third party system that I want to always contain the SessionURL. So I only want to encode this single URL always with the sessionID to minimize any security issues...
Thank you very much
Jan
The jsessionid isn't actually a request parameter, it's encoded on to the URL itself, and then decoded and removed by the container before it gets as far as your controller. The value of jsessionid itself can be retrieved from HttpSession.getId().
If you want to stop Tomcat from using cookies, then you can provide a tomcat-specific context.xml file under WEB-INF, containing something like this:
<Context cookies="false" path="/path/to/my/webapp">
</Context>
This will disable all cookies for that webapp, and tomcat should then automatically encode all session IDs on to the URL instead.