Invalidating previous session at Login: JSF 2 - session

I have a filter to be called which finds, after every page is requested if the user & session is privileged and valid respectively. But I want to invalidate the session at beginning, just before the login. Because if someone does not log out it is capturing that session if active, while next login. There is an index.jsp which is redirecting to the page after doing this job. but if the login page is hit directly then it captures the previous session.
LoginManagedBean.java
public LoginManagedBean() {
super(FacesContext.getCurrentInstance().getExternalContext());
System.out.println(FacesContext.getCurrentInstance());
System.out.println(FacesContext.getCurrentInstance()
.getExternalContext());
user = new UserBean();
}
Index.jsp
request.getSession(false).invalidate();
String redirectPage = null;
redirectPage = request.getContextPath()+"/xhtml/login/loginHome.xhtml";
Another problem is although I have index.jsp as welcome-file the "loginHome.xhtml" still opens directly from hitting the context root. Thats when the session invalidation is not happening.
web.xml
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
Thanks.. !!

Related

Model.class and session Spring

Is the Model.class(or request scope) affected in any way by the current session or actions done to that current session?
One scenario below,
Real life application would be request->user logging off-> request access.
model.addAttribute("inputForm",inputForm);
session.invalidate();
if(model.containsAttribute("inputForm")) //true or false?
Some artifact I have dug up,
"
In struts-config.xml
scope = "session"
means throught the application ( till the session gets expired). Your can keep the values in session no matter how many JPSs you are visiting of that application. It remains there in session until you close your browser.
scope="request"
means for that particular action only you are keeping the values. In this if you call another action or redirects to another JSP , it gets removed.
Another difference is that :-
request - Beans that are visible within a single JSP page, as well as to any page or servlet that is included in this page, or forwarded to by this page. (Request attributes)
session - Beans that are visible to all JSP pages and servlets that participate in a particular user session, across one or more requests. (Session attributes) "- http://www.coderanch.com/t/462078/Struts/Difference-Request-scope-Session-scope - Vinod Vinu
More about scopes
How to choose the right bean scope?

Tomcat 7 writing same JSession cookie on browser restart

I have the following configuration in tomcat configuration files :
<session-config>
<session-timeout>10</session-timeout>
<cookie-config>
<domain>myapp.mycompany.com</domain>
<http-only>true</http-only>
<secure>false</secure>
</cookie-config>
<tracking-mode>COOKIE</tracking-mode>
<Context path=""
docBase="ROOT"
sessionCookieName="mycookiename"
sessionCookieDomain="myapp.mycompany.com"
sessionCookiePath="/"
useHttpOnly="true"
reloadable="false">
<WatchedResource>WEB-INF/web.xml</WatchedResource>
</Context>
As configured above , the cookie is getting set as "session only" in browser ..and on browser quit its getting deleted as expected. But when I am opening the browser again and hitting my application URL again, same JSESSIONID is getting written to the cookie.
Why is it behaving that way ? Isn't it supposed to write a new jsessionid every time ?
It finally appears that the issue was that in Mac i have to actually quit the browser, rather than hitting its close button ...

show session expired message for longer time before redirecting to login page

All,
in my liferay portlet when the session expires, the page gets redirected to login page.
Before redirecting to login page we are showing the message saying Session expired, redirecting to login page. Problem is that the message just flashes before the login page appears. I want to show this message say for some 3 sec before redirecting to login page. Is there any portal-ext property to specify this. My current contents of portal-ext.properties file is
session.timeout.warning=1
session.timeout.auto.extend=false
session.timeout.redirect.on.expire=true
help..
session.timeout.warning indicates the duration of the countdown warning.
For eg., if it is set to 1, it means User will be warned for 1 minute.
Below configuration in web.xml indicates that if User remains idle for 30 minutes without doing any activity, his Session will be destroyed.
<session-config>
<session-timeout>30</session-timeout>
</session-config>
For more details on this behaviour, please read this bug in session warning interpretation post.
As a side note there is a nice Jquery plugin for your requirement.
If you want Session to be destroyed after 30 mins but at 29th minute you want to Warn the User, then your code will look like below,
$j.idleTimeout('#dialog', 'div.ui-dialog-buttonpane button:first', {
idleAfter: 10440, // 29mins
..
..
Now as you know your session will expire after 30 mins. So, after 30th min, your session will expire and return to your configured page.
This is possible and you can take help of following JQuery plugin which provides this feature with customization at different levels. You can configure these customization when the plugin is initialized, like one below.
....
force: 300000,
....
https://www.jqueryscript.net/other/Session-Timeout-Alert-Plugin-With-jQuery-userTimeout.html
Demo: https://www.jqueryscript.net/demo/Session-Timeout-Alert-Plugin-With-jQuery-userTimeout/

Redirect after JSF Ajax (ViewRoot) update

I'm using omnifaces FullAjaxExceptionHandler to redirect when any exception is fired with ajax request, in my case to caught ViewExpiredException.
I'll try to explain my case:
1) I have the index.xhtml page with a commandButton (ajax request) to invalidate the session and return an action like this "/login?faces-redirect=true".
2) Open index.xhtml two times in the same browser.
3) In the first index.xhtml click in the button (the session is invalidate and redirected to login.xhtml)
In this point take in account I have a custom PhaseListener to check if the user is sucessfully logged, login.xhtml is for public access but index.xhtml is restricted for authorized users, web.xml for view expired and 403 error is:
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/index.xhtml</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/403.xhtml</location>
</error-page>
4) Go to the second index.xhtml (session is invalidated in this moment), now click in the button to launch the exception.
FullAjaxExceptionHandler catch the ViewExpiredException and try to render index.xhtml, but in the same time my phaselistener is checking if the user is authorized, like the session was invalidated, the user is not authorized and my PhaseListener fire responseSendError(403), but is not showing 403.xhtml, because is an ajax request.
How I can send an 403 error to show 403.xhtml from my PhaseListener? responseSendError is cancelling the normal process for FullAjaxExceptionHandler, in this moment when that exception happens no redirection take place.
In addition, to clarify when the view expire I need redirect to index.xhtml because in production I'm using a CAS (Central Authentication Service).
The concrete problem is in essence unrelated to the FullAjaxExceptionHandler. You'd still have had exactly the same problem when not using it. It's not possible to use responseSendError() on ajax requests for at least 2 reasons:
The ajax response must have status 200 in order to be successfully processed.
The ajax response must represent a valid JSF ajax XML structure, not a plain HTML page.
Inside a PhaseListener, your best bet is to use ExternalContext#redirect().
ExternalContext ec = context.getExternalContext();
if (context.getPartialViewContext().isAjaxRequest()) {
ec.redirect(ec.getRequestContextPath() + "/403.xhtml");
} else {
ec.responseSendError(403, "Unauthorized");
}
True, this ends up in a HTTP 200 response, but that's so far the best you can get when you want to show the error page in its entirety in case of an ajax request.
Unrelated to the concrete problem, if a ViewExpiredException is been thrown, then the cause is in almost all cases an expired session. It would make more sense to just let the exception's error page point to /login.xhtml directly instead of /index.xhtml. Or, at least more user friendly, to some /expired.xhtml page with therein an explanation why the enduser ended up in there and what his options are, along with some links.

ViewExpiredException not thrown on ajax request if JSF page is protected by j_security_check

I have a JSF page which is not protected by j_security_check. I perform the following steps:
Open the JSF page in a browser.
Restart the server.
Click a command button on the JSF page to initiate an ajax call.
Firebug shows that a ViewExpiredException is raised, as expected.
Post:
javax.faces.ViewState=8887124636062606698:-1513851009188353364
Response:
<partial-response>
<error>
<error-name>class javax.faces.application.ViewExpiredException</error-name>
<error-message>viewId:/viewer.xhtml - View /viewer.xhtml could not be restored.</error-message>
</error>
</partial-response>
However, once I configure the page to be protected by j_security_check and perform the same steps listed above, strangely (to me) the ViewExpiredException is no longer raised. Instead, the reponse is just a new view state.
Post:
javax.faces.ViewState=-4873187770744721574:8069938124611303615
Response:
<partial-response>
<changes>
<update id="javax.faces.ViewState">234065619769382809:-4498953143834600826</update>
</changes>
</partial-response>
Can someone help me figure this out? I expect it to raise an exception so I can process that exception and show an error page. Now it just responds with a new ViewState, my page just got stuck without any visual feedback.
I was able to reproduce your problem. What is happening here is that the container invokes a RequestDispatcher#forward() to the login page as specified in security constraint. However, if the login page is by itself a JSF page as well, then the FacesServlet will be invoked as well on the forwarded request. As the request is a forward, this will simply create a new view on the forwarded resource (the login page). However, as it's an ajax request and there's no render information (the whole POST request is basically discarded during the security check forward), only the view state will be returned.
Note that if the login page were not a JSF page (e.g. JSP or plain HTML), then the ajax request would have returned the whole HTML output of the page as ajax response which is unparseable by JSF ajax and interpreted as "empty" response.
It is, unfortunately, working "as designed". I suspect that there's some oversight in the JSF spec as to security constraint checks on ajax requests. The cause is after all understandable and fortunately easy to solve. Only, you actually don't want to show an error page here, but instead just the login page in its entirety, exactly as would happen during a non-ajax request. You just have to check if the current request is an ajax request and is been forwarded to the login page, then you need to send a special "redirect" ajax response so that the whole view will be changed.
You can achieve this with a PhaseListener as follows:
public class AjaxLoginListener implements PhaseListener {
#Override
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
#Override
public void beforePhase(PhaseEvent event) {
// NOOP.
}
#Override
public void afterPhase(PhaseEvent event) {
FacesContext context = event.getFacesContext();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
String originalURL = (String) request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
String loginURL = request.getContextPath() + "/login.xhtml";
if (context.getPartialViewContext().isAjaxRequest()
&& originalURL != null
&& loginURL.equals(request.getRequestURI()))
{
try {
context.getExternalContext().invalidateSession();
context.getExternalContext().redirect(originalURL);
} catch (IOException e) {
throw new FacesException(e);
}
}
}
}
Update this solution is since OmniFaces 1.2 been built into the OmniPartialViewContext. So if you happen to use OmniFaces already, then this problem is fully transparently solved and you don't need a custom PhaseListener for this.
The above AjaxLoginListener solution works for me. Interestingly we are using omnifaces 3.11.1 but the OmniPartialViewContext is not working in my scenario. This is because the check for the loginViewId does not match the current viewId since I have an error-page in my web.xml for org.jboss.weld.contexts.NonexistentConversationException. Note that when AjaxLoginListener is fired for me it throws an exception on the call to context.getExternalContext().invalidateSession(); so it never calls the redirect(). So I'm not sure if my scenario is exactly the same as the original one in this thread. Here are the steps I use to recreate my scenario:
Visit an xhtml page with an ajax command button.
Wait for the session to timeout.
Click the ajax command button.
User is redirected to the error-page mapped to the NonexistentConversationException in web.xml
Click a link on that page which requests a secured url
System shows login page - login.
Click the link that takes you to the xhtml page that contained the ajax command button in step 1.
System shows the partial response containing the NonexistentConversationException error-page contents.
Is it possible that the AjaxLoginListener is working because it is mapped to PhaseId.RESTORE_VIEW whereas the OmniPartialViewContext is mapped to PhaseId.RENDER_RESPONSE?

Resources