Why Wicket redirects to the home page after tomcat restarting? - wicket

Let's say I have three pages in my application: SignInPage, HomePage and AnotherPage.
When I open the application for the first time it shows me SignInPage. After authorization it redirects me at HomePage. After that, I manually open AnotherPage, restart the servlet container, and press F5 button. And wicket redirects me at HomePage again, not in AnotherPage. Why is this happens and how to avoid that?
--
All pages mounted with mountPage method. Each page is statefull and has #AuthorizeInstantiation annotation. The application class extends AuthenticatedWebApplication and overrides methods like this:
#Override
protected Class<? extends WebPage> getSignInPageClass() {
return SignInPage.class;
}
#Override
public Class<? extends Page> getHomePage() {
return HomePage.class;
}
Also, in the config I have the following row:
getApplicationSettings().setPageExpiredErrorPage(ErrorSessionExpiredPage.class);
(But I've never seen this page open)
Update:
The solution is to add the following code to the SignInPage class:
#Override
protected void onBeforeRender() {
if (((AuthenticatedWebSession)Session.get()).isSignedIn()) {
continueToOriginalDestination();
setResponsePage(Application.get().getHomePage());
}
super.onBeforeRender();
}

When you restart the servlet container it looses all its sessions. On the next request Wicket detects that this is a new http session and should redirect you to the SignInPage, not directly to the HomePage. Only after successful authentication you should see the HomePage.
If you use Component#redirectToInterceptPage(Page) + Component.continueToOriginalDestination() then you can land at AnotherPage after successful authentication. See Component.continueToOriginalDestination()'s javadoc for more information.

restarting the servlet container gives you new session without information which pages expired so that's why you are redirected to HomePage.
Please check this: https://users.wicket.apache.narkive.com/3OtYz8xj/pageexpiredexception-not-working-on-session-expired-wicket-1-5-11

Related

Handle session time out with Wicket

I'm working on a wicket legacy-project and i'm trying to fix a bug with the session time-out.
Basically I'd like to have a redirect to a customed error page after session times out.
This is what I did:
web.xml :
<session-config>
<session-timeout>1</session-timeout>
</session-config>
in the application class:
#Override
public void init() {
super.init();
getApplicationSettings().setPageExpiredErrorPage(ErrorMessagePage.class);
This is not working. I mean after session time out, nothing happens.
What am I doing wrong?
EDIT 04.05.20
Based on the feedback from Martin I tried to implement a session validaty checker:
public class SessionValidityChecker implements IRequestCycleListener {
#Override
public void onBeginRequest(RequestCycle cycle) {
HttpServletRequest request = (HttpServletRequest) cycle.getRequest().getContainerRequest();
boolean sessionValid = request.isRequestedSessionIdValid();
if (!sessionValid) {
cycle.setResponsePage(SessionExpiredPage.class);
}
}
}
and in Application.class
public void init() {
super.init();
getRequestCycleListeners().add(new SessionValidityChecker());
}
Also what I may should have specified in my first post is that I use the wicket SignInPanel for authentification. After timeout, I'd like the user to be logged out and redirected to a specific page.
This is what I've tried with the above code, but after session time out, no redirect happens. Even worst, the user is still signed in. What am I missing?
You are mistaking page expiration with session expiration.
Stateful pages are stored in a PageStore (disk) and the store may grow up to some predefined size. Once this size is reached the oldest page is removed to make room for the newest one.
If your user uses the browser Back button many times at some point Wicket will throw PageExpiredException for the deleted page.
In your case when the session expires usually the web server (e.g. Tomcat) will just create a new one. If your application has authentication enabled then it will detect that there is no authenticated user in the new http session and most probably will redirect the user to the login page.
If there is no authentication in place then Wicket will create a new instance of the requested page and render it. You can change this by changing PageSettings#recreateBookmarkablePagesAfterExpiry to false
(see https://github.com/apache/wicket/blob/79f63f66eb588a5d69e9feff7066f1244f61f387/wicket-core/src/main/java/org/apache/wicket/settings/PageSettings.java#L46)
You may use javax/servlet/http/HttpServletRequest.html#isRequestedSessionIdValid() method to find whether the the request came with an expired JSESSIONID cookie/url. If it is false then the web server just created a new HttpSession. You can do the check in Wicket's IRequestCycleListener#onBeginRequest()

Liferay : How to show a Configured Page once User Enters Valid Credentials

I am using Liferay 6.1 version .
Once a User enters http:localhost , i am displaying my Web Page called "/ravi" which consists of my Custom Portal as shown
I have configured this below properties under portal-ext.properties as shown
auth.forward.by.last.path=true
default.landing.page.path=/web/guest/ravi
Please see the screen shot of my Custom Portlet shown when the users enters http:localhost
Now my requirement is that i need to show another page ("/web/guest/test") if he enters valid crendentails .
In my processAction class , i am doing this way
public class ValidateUser extends MVCPortlet {
public void processAction(ActionRequest request, ActionResponse response) {
String userName = (String) request.getParameter("userName");
String password = (String) request.getParameter("password");
try {
// Contatcs DB and validates the credentials here
// Please let me know how can i show the Configured Page if his credentials are valid ??
}
catch (Exception e) {
}
}
}
Edited Part
Thank you very much for the answer with respect to the default login.events.post .
I am new to Liferay , so i may be doing a mistake here , so please help me if i was doing anything wrong .
I followed these steps :
Created a New Portlet named "MyLogon" Portlet and in its view.jsp created a form with two text fields (Login and Password ) and a submit button .
On click of that Submit Button , i was actually calling my processAction Method and making a DB call to validate Users from mysql db .
2.Then i created a page inside /web/guest/ravi and added this "MyLogon" Portlet to this new page /web/guest/ravi
Then configured this below properties under portal-ext.properties
auth.forward.by.last.path=true
default.landing.page.path=/web/guest/ravi
This is what i did .
And when entering http:localhost:8080 , it displayed taht page .
Please tell me if i am doing anything wrong
Edited 2nd Part
I have understood some part of your answer and i have these questions .
Could you please help
I need to validate Users based on the Data present inside my DataBase , so for this i need to do the below thins .
I need to create a Hook , to overdide this property
login.events.pre=com.LoginAction
public class LoginAction extends Action {
public void run(HttpServletRequest req, HttpServletResponse res) {
// Here i need to make a Database call to validate User Credentials and then do redirect him to the page i wanted ??
}
}
You need to create a Hook and override the default login.events.post
Below code for your reference,
public class LandingPageAction extends Action {
public LandingPageAction()
{
}
public void run(HttpServletRequest request, HttpServletResponse response) throws ActionException
{
try
{
doRun(request, response);
}
catch(Exception e)
{
throw new ActionException(e);
}
}
protected void doRun(HttpServletRequest request, HttpServletResponse response) throws Exception
{
String homeRedirect="/web/guest/test";
LastPath lastPath = new LastPath(StringPool.BLANK, homeRedirect);
session.setAttribute("LAST_PATH", lastPath);
}
}
There are few things which I don't understand here. You are hitting localhost:8080, but screen shot shows that you are already logged in (there is a SignOut link and user Ravi Kiran is already logged in), but still there is a login page shown.
default.landing.page.path comes into picture when you are loggedin user. Are you hitting localhost:8080 or localhost/web/guest/Ravi ? You are not logged in yet, so it should not redirect to /web/guest/Ravi.
You could reuse the default Authentication code in Liferay. Not sure why you are taking User credentials from request parameters and making DB call yourself.
Edited as per the update in the question
1. The default Login Page of Liferay (the one that you see when you freshly download and hit localhost:8080 comes from this path
..\default\deploy\ROOT.war\html\portlet\login.
There is a login.jsp in this path which you can edit and give your own look and feel.
You can find below entry in this login.jsp page
<portlet:param name="struts_action" value="/login/login" />
This has a corresponding entry in ../deploy/ROOT.war/WEB-INF/struts-config.xml
<action path="/login/login" type="com.liferay.portlet.login.action.LoginAction">
<forward name="portlet.login.login" path="portlet.login.login" />
</action>
You can open up the source code and look into com.liferay.portlet.login.action.LoginAction method.
This performs a basic Authentication as per your passwords.encryption.algorithm= and passwords.digest.encoding=
configuration in portal-ext.properties file. LoginAction will perform basic authentication and will redirect all
users as per path mentioned in default.landing.page.path=
If you want (some) Users to redirect to (some) other path(conditionally), you can use the code I have mentioned above by writing a Hook.
2. Once authenticated, you can login and create a Page (in your case its "ravi"). You can add your custom Portlet to this Page. You should not write a cutom portlet which will do authentication once you are already logged in

Wicket setResponsePage after a session timeout

This is the onSubmit() method of my Wicket 1.5 application's login page:
#Override
public void onSubmit() {
super.onSubmit();
User theUser = loginForm.getModelObject();
/* call a DAO function to check the user's credentials */
if(/* DAO call succeeds*/) {
MyCustomeSession authSession = (MyCustomSession)Session.get();
authSession.success("Welcome, " + theUser.getFullName());
setResponsePage(new HomePage());
}
else {
loginForm.error("Username or password was incorrect");
}
}
This works fine for initial login, and for logout then log back in, in that the next thing seen is the Home page with the Welcome message.
Upon session timeout, this application redirects the user back to this same login page, with a feedback message "Your session has expired blah, blah" and allows user to enter username and password again. If the user does this, the login is successful: menus that were hidden become visible, the Welcome message shows, etc.
However, the page shown remains the Login page, with additional feedback messages for the required username and password (even though both had been entered and the login succeeded). Here is a clipped screen shot:
Is this some weird thing with Wicket? Is there a fix or a work-around?
Well, it seems that a page which is a application.setPageExpiredErrorPage(page) cannot subsequently do a setResponsePage(new HomePage()); but must instead do setRepsonsePage(HomePage.class);.
Meanwhile, when this LoginPage is just a normal page, i.e. on initial login or after a logout, it must use setResponsePage(new HomePage()); This doesn't make much sense, but that seems to be the Wicket way.
So I added a boolean value to the LoginPage constructor called isTimeout and call one or the other version of setResponsePage accordingly.

Authentication Required Dialog

I run into problem with login screen in netbeans rcp.
server side : glassfish v 3.1 , ejb and HessianServlet with basic auth in web.xml
client side : netebeans rcp 7.0 and server side Api.
on the server used custom realm and client provides UserName and Password after splash screen, in custom login panel runing on top of DialogDescriptor
login panel code:
public class Installer extends ModuleInstall {
...
#Override
public void restored() {
DialogDescriptor loginDialog = new DialogDescriptor(panel, "Login Dialog");
loginDialog.setModal(true);
loginDialog.setClosingOptions(new Object[]{});
loginDialog.setOptions(new Object[]{});
loginDialog.setButtonListener(al);
loginDialog.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (NotifyDescriptor.CLOSED_OPTION.equals(evt.getNewValue())) {
LifecycleManager.getDefault().exit();
}
}
});
DialogDisplayer.getDefault().notifyLater(loginDialog);
...
}
this login panel simply invokes one secured method on server side and if exception do not happend and
returned String[] contains user Name and Surname, then login screen disposes and rcp shown to client.
in login panel :
HessianProxyFactory proxy= new HessianProxyFactory();
proxy.setUser(user);
proxy.setPassword(password);
LoginObject loginObject = xxx.create(LoginObject .class, "<a href="http://localhost:port/trali/vali">http://localhost:port/trali/vali");
String[] value=loginObject .isAppUser("login name");
if(value==null){
//message login failed
}else {
//dispose login screen and show main app
}
everything is OK till client provides correct user name and password, but if login faild on
server Netbeans RCP pop ups Authentication Requires Dialog like in web browser
basic auth dialog.
How to disable this dialog?
thanks in advance!
Tools > Options > General
Proxy Settings: No Proxy
[OK]
That will stop the Proxy Authentication (FTP/SFTP) popup. Or set your proxy settings to something that works.
You can override this dialog with the method Authenticator.setDefault(Authenticator).
If you do attempt to disable the authentication, by overriding the default authenticator, you will need to take that into consideration in your client code... since you may get a stream of 'Unauthorized' responses.
disable your proxy configuration by going to tools->option->general->no proxy

GXT: How to bring the login page when session expires

I am developing a web application using GXT, Hibernate, mysql etc. There is a login page for the application. Actually I am getting problem to set the login page when the session expires. We can set the timeout in the web.xml file but in that case we can't redirect to login page.Can you tell me how to achieve that.
You can not do a server side redirect because the application is entirely AJAX. What you can do is use the GWT Timer class and for every one of your RPC calls check/reset the timer. If the "session" expires then you do a redirect to the login page via a History token. This was the easiest way for me
Some other reading:
http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/b9eab8daaa993c83/d0192d356045e061?pli=1
http://gwt-ext.com/forum/viewtopic.php?f=9&t=1682
I have used the concept of throwing an exception in the server side when the session expires and then tried to catch the exception in the client side. I don't know whether there is any better way to do that.
On the server side, you can check if the session is expired and if so, throw a custom exception.
On the client side, on every async call you do a check for this known situation and react to it. You can create an abstract class for AsyncCallback that you will subclass for each GWT RPC call:
public abstract class SessionExpiredAwareAsyncCallback<T> implements AsyncCallback<T> {
#Override
public void onSuccess(T returnObject) {
doOnSuccess(returnObject);
}
#Override
public void onFailure(Throwable exception) {
if (exception instanceof SessionExpiredException) {
goToLoginPage();
} else {
doOnFailure(exception);
}
}
public abstract doOnSuccess(T returnObject);
public abstract doOnFailure(Throwable exception);
}
You can use gwteventservice to fire an event from the server to the client.