Force page expiration in wicket 1.5.8 - java

I'm trying to expire all previous versions of a given page with Wicket 1.5.8. In wicket 1.4, it was done by getPage().getPageMap().clear(). Now in wicket 1.5, page map is gone, and I can't figure out how to dot that.
My use case is that I have a wizard (http://www.wicket-library.com/wicket-examples/wizard/) to create/edit an entity. When the wizard is submitted, the user is redirected to the entities list. At this point I don't want the user to be able to use the browser back button to go back to the wizard in the state it was, and thus want to expire previous versions of the page with the wizard (I am using getPageSettings().setRecreateMountedPagesAfterExpiry(true); so the mounted page will be recreated in a blank state if the page expires when the user goes back, which is what I want).
Looking around I found the possibility to use Session.get().clear(); which removes all pages from the Session (I don't know if the 1.4 version was removing all pages or just all versions of the page used to access the PageMap - which would be better for multi-tab support). However, using that works only partly, as the last page is not expired.
Supposing the wizard is mounted at /wizard, redirecting to /list at the end, the flow would be something like: /wizard?1, /wizard?2, /wizard?3, /list. Now when I use the back button, /wizard?3 is not expired, although /wizard?1 and /wizard?2 are as expected. The session clearing and sending to the list page are done in the onFinish method of the wizard, which reads like this:
#Override
public void onFinish() {
Session.get().clear();
Session.get().getFeedbackMessages().add(new FeedbackMessage(..));
setResponsePage(ListPage.class);
}
So, come to the question itself: would anyone know how to get the expected behaviour, i.e. expiring /wizard?3 as well?
Thanks
Note: ListPage is a bookmarkable page and I tried as well with setResponsePage(new ListPage());
Update with what I finally did base on Andrea's suggestion
It is to be noted that my application uses a custom session object extending wicket's Session; let's call it AppSession.
in AppSession, I added a boolean clearRequested attribute (defaults to false)
in AppSession, I added a static void method requestClear() which is just a shortcut to set clearRequested to true in the session
in the onFinish() of my wizard, just before calling setResponsePage, I call AppSession.requestClear()
lastly I just add a RequestCycleListener to my application.
getRequestCycleListeners.add(new AbstractRequestCycleListener() {
#Override
public void onBeginRequest(RequestCycle cycle) {
super.onBeginRequest(cycle);
AppSession session = AppSesssion.get();
if (session.isClearRequested()) {
session.clear();
session.setClearRequested(false);
}
}
});
Now anytime I need to clear session after an action in order to expire pages, I juste call AppSession.requestClear() and in the next request the session is cleared.

you could clear your session in ListPage. Since this page is bookmarkable you could pass it a page parameter indicating that ListPage must get rid of the pages in session.

Related

Wicket: double login required due to extended browser info

I have a Wicket 8.6 application. Currently, when logging in to the application, mostly (does not always happen) the user has to login twice. After the first login (after entering the credentials and clicking the submit button) a white page appears saying "If you see this, it means that both javascript and meta-refresh are not support by your browser configuration. Please click this link to continue to the original destination." This is the BrowserInfoPage. After a few seconds the user is redirected to the login page again where he/she has to enter his/her credentials again and press the login button. This time, the user logs in successfully. My question is, how do I prevent that the user hast to enter his/her credentials twice.
From my research I know that it has something to do with the collection of extended browser info. In the init method of my WicketApplication class, I had the following code:
getRequestCycleSettings().setGatherExtendedBrowserInfo(true);
However, I already commented out this code several month ago. For some reason, the described effect occurs for every new deploy now. Maybe a newly added package in the application is the reason for it. I don't know. Is there a possibility to prevent this second login maybe by creating a customized bowser info page which forwards the login? Please point me in the right direction. Thanks.
After some research, I came up with a work around. It is probably not very efficient but it works for me so far. In my custom Session class which inherits from AuthenticatedWebSession, I added the following code.
#Override
protected WebPage newBrowserInfoPage() {
final Request request = RequestCycle.get().getRequest();
if(request.getUrl().toString().contains("LoginPage")) {
if(!isSignedIn()) {
signIn(username, password);
}
PageParametersEncoder encoder = new PageParametersEncoder();
PageParameters parameters = encoder.decodePageParameters(request.getUrl());
String url = parameters != null && parameters.get("originUrl") !=null && !parameters.get("originUrl").isNull() && !parameters.get("originUrl").isEmpty()?
parameters.get("originUrl").toString("pages/home"):"pages/home";
String finalUrl=url.startsWith("pages/")?url.substring("pages/".length()):url;
throw new RedirectToUrlException(finalUrl);
}
return super.newBrowserInfoPage();
}
Some explanation to the code. As mentioned in the question, I want to prevent the user from logging in multiple times. Thus, I check if the request comes from the LoginPage and perform my work around only in that case.
During my implementation, I realized, that the method newBrowserInfoPage is called in the process when I call session.signIn(username,password); on my LoginPage. In this signIn process the authenticate method of my custom Session is called but the signedIn flag in the AuthenticatedWebSession is not changed (keeps false on successfull authentication). Is this a bug? Thus, I have to login again to set the flag to true.
Finally, I read the URL of the LoginPage where I have stored the target URL and forward the user to the target URL.
I am aware this is probably not the best approach but it is the only solution I came up with. If someone has a better idea, I am happy to hear it.

Change session variables without reloading page

So my webpage has a Link remove Advertisment which should remove the ads from my website and remember to not show any ads in the rest of the session.
My approach at was first was a private static Variable in the controller, which could be set via methods.
private static boolean Ads = true;
public static void closeAds() {
Logger.debug("Ads removed");
Ads = false;
}
I did some research and found out that the session() method provided by the play framework probably would be more suitable.
Anyway my problem is, I don't know how to call those controller methods within my html page, since every HTTP request has to have an response and I don't want to reload my page, I only want to set the variable or session variable.
I figured Ajax could be the answer? I couldn`t come up with anything yet
Play keeps session information on client side within a signed cookie.
So you have 2 options (I would go with the 2nd):
1) Ajax call to update play's session data (because you will not want to modify this on client side with javascript since it is a signed cookie and break things)
2) Create another cookie for keeping the advertisements on/off flag and modify it by javascript on clientside, and then you can check the value of this cookie on server side to achieve ads on/off. This will prevent you from doing an extra ajax call.

how to send an alert when session expires

i wanted to throw an alert when session expires and when you press ok button in the alert box then it will take you to login page. For this i thought to create a timer and timertask and in the run method of the later class i will check if the session exists or not. So for this i tried to create a class in jsp page but it is showing error. i can create in servlet but all my pages are in jsp and so this idea is not useful.Now i created a sessionlistner and in the session destroyed method i want to link to login page but i have a problem here too.I can not use response method in the sessiondestroyed method.Please tell me are there any other ways
You can use JavaScript like:
var sessionTimeout = "<%= Session.Timeout %>";
function DisplaySessionTimeout()
{
//assigning minutes left to session timeout to Label
document.getElementById("<%= lblSessionTime.ClientID %>").innerText =
sessionTimeout;
sessionTimeout = sessionTimeout - 1;
//if session is not less than 0
if (sessionTimeout >= 0)
//call the function again after 1 minute delay
window.setTimeout("DisplaySessionTimeout()", 60000);
else
{
//show message box
alert("Your current Session is over.");
}
}
For more details visit here
First, you can creates totally client side solution: use setTimout() when page is loaded first time. Use either hard-coded or arrived from server value of timeout. When timer is triggered use document.location = login.html (or something like this) to arrive to login page.
This solution is "fast and dirty."
Better solution should be based on real session expiration. You can create AJAX call that tries from time to time special URL. This URL should return true/false that means that session is expired or not. When session is expired you should redirect the page to login screen. The problem with this solution is that the fact that you request the session state refreshes it. To solve this problem you can either perform the request to different server or (probably) remove session cookie from the polling request, so it will be performed in session different from the main session.
With Tomcat you can create a JS timer that make a simple AJAX call.
If the call return without errors the session is valid, if the call fails you can consider the session expired. On default behavior Tomcat deosn't renew sessions if you don't explicitly call it.
I had the opposit case: link
This problem is already solved by the Java EE Spec. You should consider using web.xml configurations to handle session timeout issues. It has specific tags for handling all of this. Some of the tags are:
<login-config> ... </login-config>
The above tag lets you used FORM based authentication where you can specify your login HTML resource.
<security-constraint> ... </security-constraint>
The above tag lets you specify the URLs you would like to secure. And finally the session timeout tag itself, which allows you to specify the session timeout in millis.
Once you do the above, the container would automatically take the user to the login page when he requests a secure URL.
Here is the web.xml reference.
From a messaging standpoint, there are multiple ways of seeing the problem:
The fact that system is taking the user back to the login page and forcing him to login, is indicator enough for him/her.
You could provide a generic message on the login page itself.
Device some tricky flag based or querystring logic to show the message on the login page.
Came across this link in StackOverflow itself which provides a strategy you can implement in the login page itself. Have not tried this though.
This in my mind is a trivial problem compared to the whole session timeout strategy itself.

Session expired - How to terminate the session in the original tab of the browser

I have a web app in which I have set the maximum inactivity time to 10 min. This is just for testing purposes. Basically, if the session has timeout and I click on a link, the following window browser checks if the session is valid. This is also working fine. If this happens, I get a message saying "session has expired, please login again". But the orginal window stays open and if I click on the same link, then this time is letting me see the page, even though I have not logged in again. Why is this?
I am using the session.invalidate() if the session is expired, to make sure all attributes are removed, but this is not working somehow.
I using the following part of the code at the beginning of the page:
if(request.isRequestedSessionIdValid() == false)
{
response.sendRedirect("expired.jsp");
session.invalidate();
return;
}
This is working the first time this page is loaded, but if I click on the link again to load it once more, this condition is not met, despite the session being timeout.
Could you please give any advice?
Update: My webapp works the following way:
User gets to the index.jsp page and uses an ID and password to access the system, then there is a BRMspace.jsp page where there is a folder structure for the user to access depending on the documents they are after. By clicking on each folder, a table with a database populated is displayed for the user to download the documents they want.
The issue I am having is that after 10 min of inactivity, if the user clicks on one folder on the initial screen, the database is not displayed, instead I get a message saying that session has expired and I am redirected to the login page, which is ideal. However, if I click on the same folder again, this time I get the usual table with the data and all documents. It seems that after one click, the inactivity time is not longer valid.... so I am not sure how to do... I am using session.invalidate() to delete all data about the session, but obvioulsy is not working.
I need the user to be redirected to login page again after the inactivity time no matter where the user clicks on.
This is an update:
Hi there, I have to re-take this question, which has been very helpful to resolve 90% of my original issue, but I still have one left.... on my web application, when user logins, they have a list of options to click on, each click takes them to a new tab which are different .jsp files... if session has expired, these tabs show the expired.jsp file, which is perfect... however, the original tab, the one that is shown after the user logins, stays live, I mean, it does not show that the session has expired... what can I do in this case?...
A web session doesn't have anything to do with any login or access credentials. It simply means that the container has data saved for you that can be retrieved if you pass in the correct session token (either by cookie or request parameter). If you have been inactive on the site for a period of time (in your case 10 minutes), that data is discarded and if you check for a sessions validity, you will discover whether the data is still around or has been discarded. If the session has expired, the container will automatically create a new session for you to handle future requests. And if another request is sent to the server before the timeout expires, that requested session will not be invalid.
If you are trying to prevent people from access a page when they have not logged in, you actually need to put some value into the session that says they have authenticated, and check that value. Just checking whether their requested session is valid is not sufficient.

Does NavigationHandler.handleNavigation() clear the flash?

I am using JSF2.0 Mojarra 2.0.2.
I have a method that logs out a user and puts a logout message in the flash, forwards to the login page (which has a div that prints out the flash). However, when I use navigationHandlers handleNavigation method for some reason the flash is not being displayed. I have a similar method that forwards a user to the login page if he/she isn't logged in.
If I handle the navigation through an h:link and just call the logout method directly, the flash is displayed as normal, but if I use the handleNavigation() method, the flash is cleared for some reason.
The code in question is:
public void performLogout()
{
getFacesContext().getExternalContext().invalidateSession();
setCurrentUser(null);
getFlash().put("notice", "Successfully logged out.");
super.getFacesContext().getApplication().getNavigationHandler()
.handleNavigation(getFacesContext(), null, "login");
}
Is there some way I can keep the flash when navigating like this?
thanks.
Edit: I believe this issue is related to another issue involving the flash not being preserved during redirects when xhtml pages are in different directories: http://java.net/jira/browse/JAVASERVERFACES-1635
You're right.
The JSF 2 flash scope is currently extremly buggy, and based on the specification, will probably remain almost unusable: http://javaserverfaces.java.net/nonav/docs/2.0/javadocs/index.html
If you'd like a flash scope that works as follows, consider using CDI, and the flash scope from Seam Faces - http://docs.jboss.org/seam/3/faces/reference/snapshot/en-US/html_single/#flashscoped
"The flash scope should be active from
the moment an object is placed in the
scope, until the moment the response
has completed rendering."
--Lincoln

Categories