-
1. Re: RF4: Session timeout, how?
ssamayoagt May 16, 2011 3:07 PM (in response to ssamayoagt)After reading abot in the Web (it is a common problem) I found a solution, simple and somewhat elegant.
First, this is my environment:
- Glassfish 3.1 (JSF 2.1.x / Servlet 3.0)
- Richfaces 4.0
- Container managed secutiry
When server receives a request and session is already expired it doesn't sends a redirect to login page, it sends the login page itself.
JSF AJAX js code doesn't expect that, it expects an XML which may contain partial rendering information, error information or redirect informatiom.
So, instead of setting login-form-page to a real page (JSF or HTML) I set to a servlet;
<login-config>
<auth-method>FORM</auth-method>
<realm-name>planillagt</realm-name>
<form-login-config>
<form-login-page>/ingreso</form-login-page>
<form-error-page>/ingreso</form-error-page>
</form-login-config>
</login-config>
Which does the redirect to real login page:
@WebServlet("/ingreso")
public class Ingreso extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doService(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doService(request, response);
}
protected void doService(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String facesRequest = request.getHeader("Faces-Request");
if (facesRequest != null && facesRequest.equals("partial/ajax")) {
String url = MessageFormat.format(
"{0}://{1}:{2,number,####0}{3}/ingreso.view",
request.getScheme(), request.getServerName(),
request.getServerPort(), request.getContextPath());
PrintWriter pw = response.getWriter();
pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
pw.println("<partial-response><redirect url=\"" + url
+ "\"></redirect></partial-response>");
pw.flush();
} else {
response.sendRedirect(request.getContextPath() + "/ingreso.view");
}
}
}
If servlet detects that request comes from JSF AJAX ("Faces-Request" containing "partial/ajax") responses the JSF's redirect XML else just redirects to real login page.
This is working for me now, hope that works for you also.
Regards.
-
2. Re: RF4: Session timeout, how?
denebj Jun 9, 2011 4:11 PM (in response to ssamayoagt)Hey guys
I implemented your solution - working like a charm But I noticed that on Firefox and Safari the header Faces-Request is not being send in the POST request !!
It is working with Chrome/IE. So, there is no way to detect that it is a partial/ajax
Do you any workaround for that ? Or any leads ?
Thank you
-
3. Re: RF4: Session timeout, how?
nbelaevski Jun 9, 2011 5:05 PM (in response to denebj)Hi,
I have this header sent from FF - are you checking AJAX request or common form submit?
-
4. Re: RF4: Session timeout, how?
denebj Jun 10, 2011 5:25 PM (in response to nbelaevski)Hi
It does not matter apparently, I tried from a4j component (commandbutton) and also h:commandbutton.
The result is the same, my Faces-Request value is null and when I look at Firebug I have that:
Server Apache-Coyote/1.1
Set-Cookie JSESSIONID=3D172CE279A40EE22DAB034AF930F524; Path=/; Secure
Location https://localhost:8443/servlet/
Content-Length 0
Date Thu, 09 Jun 2011 21:30:39 GMT
Request Headersview source
Host localhost:8443
User-Agent Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip, deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Connection keep-alive
Referer https://localhost:8443/settings/
Cookie __utma=111872281.1694059113.1305215609.1307648008.1307654090.70; __utmz=111872281.1305215609.1.1.utmcsr
=(direct)|utmccn=(direct)|utmcmd=(none); JSESSIONID=F4BEF48E826788A2E972A6EE3AC4A97B; __utmc=111872281
; __utmb=111872281.14.10.1307654090
And from an A4J action :
Host localhost:8443
User-Agent Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip, deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Connection keep-alive
Faces-Request partial/ajax
Content-Type application/x-www-form-urlencoded; charset=UTF-8
Referer https://localhost:8443/aircraft/
Content-Length 1231
Cookie __utma=111872281.1694059113.1305215609.1307648008.1307654090.70; __utmz=111872281.1305215609.1.1.utmcsr
=(direct)|utmccn=(direct)|utmcmd=(none); JSESSIONID=213AF872F78920A6FC581E6B496D1E90; __utmc=111872281
; __utmb=111872281.18.10.1307654090
Pragma no-cache
Cache-Control no-cache
But I am still having request.getHeader("Faces-Request") = null.
-
5. Re: RF4: Session timeout, how?
floriandupont Oct 14, 2011 4:55 AM (in response to denebj)I'm having the same issue, did you find a solution ?
-
6. Re: RF4: Session timeout, how?
denebj Oct 14, 2011 11:11 AM (in response to floriandupont)I used a filter like that :
public class SessionTimeoutFilter implements Filter {
private final Log logger = LogFactory
.getLog(SessionTimeoutFilter.class);
private String timeoutPage = "YOUR URL";
/*
* (non-Jsdoc)
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
public void init(FilterConfig filterConfig) throws ServletException {
}
/*
* (non-Jsdoc)
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
* javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
if ((request instanceof HttpServletRequest)
&& (response instanceof HttpServletResponse)) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
// is session expire control required for this request?
if (isSessionControlRequiredForThisResource(httpServletRequest)) {
// is session invalid?
if (isSessionInvalid(httpServletRequest)) {
String timeoutUrl = httpServletRequest.getContextPath()
+ "/" + getTimeoutPage();
logger.info("session is invalid! redirecting to timeoutpage : "
+ timeoutUrl);
logger.info("Control on page : "
+ httpServletRequest.getRequestURI());
String facesRequest = httpServletRequest
.getHeader("Faces-Request");
if (facesRequest != null
&& facesRequest.equals("partial/ajax")) {
String url = MessageFormat.format(
"{0}://{1}:{2,number,####0}{3}/sessionexpired/",
request.getScheme(), request.getServerName(),
request.getServerPort(),
httpServletRequest.getContextPath());
PrintWriter pw = response.getWriter();
pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
pw.println("<partial-response><redirect url=\"" + url
+ "\"></redirect></partial-response>");
pw.flush();
} else {
httpServletResponse.sendRedirect(timeoutUrl);
}
return;
}
}
}
filterChain.doFilter(request, response);
}
/**
* session shouldn't be checked for some pages. For example: for timeout
* page.. Since we're redirecting to timeout page from this filter, if we
* don't disable session control for it, filter will again redirect to it
* and this will be result with an infinite loop...
*
* @param httpServletRequest the http servlet request
* @return true, if is session control required for this resource
*/
private boolean isSessionControlRequiredForThisResource(
HttpServletRequest httpServletRequest) {
String requestPath = httpServletRequest.getRequestURI();
boolean controlRequiredLogin = !StringUtils.contains(requestPath,
"login");
return !controlRequiredLogin ? false : true;
}
/**
* Checks if is session invalid.
*
* @param httpServletRequest the http servlet request
* @return true, if is session invalid
*/
private boolean isSessionInvalid(HttpServletRequest httpServletRequest) {
boolean sessionInValid = (httpServletRequest.getRequestedSessionId() != null)
&& !httpServletRequest.isRequestedSessionIdValid();
return sessionInValid;
}
/*
* (non-Jsdoc)
* @see javax.servlet.Filter#destroy()
*/
public void destroy() {
}
/**
* Gets the timeout page.
*
* @return the timeout page
*/
public String getTimeoutPage() {
return timeoutPage;
}
/**
* Sets the timeout page.
*
* @param timeoutPage the new timeout page
*/
public void setTimeoutPage(String timeoutPage) {
this.timeoutPage = timeoutPage;
}
And add the filter to the web.xml:
<filter>
<filter-name>SessionTimeoutFilter</filter-name>
<filter-class>com.utils.SessionTimeoutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SessionTimeoutFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
And that's it, it is working perfectly.
-
7. Re: RF4: Session timeout, how?
hantsy Nov 22, 2011 9:52 PM (in response to denebj)This solution can not reuse the configuration of Spring Security paths....
in my project, some paths are public, some are private and protected which can be accessed by anthenticated user.
-
8. Re: RF4: Session timeout, how?
fernandosc Jan 20, 2012 9:29 AM (in response to ssamayoagt)I am using the above implementation, however, it does not validate the session in the call: isSessionInvalid.
Ing a session is always valid, even when it expires.
Thanks.
-
9. Re: RF4: Session timeout, how?
ravi.jrk Apr 13, 2012 10:27 AM (in response to ssamayoagt)The above servlet solution was working well in firefox. on session time out it was redirected to the proper URL. But It is not working in IE 8. We are using Richfaces 4 and the ajax repsonse is malformed.
Following is the response in IE 8.
Server returned responseText: <?xml version="1.0" encoding="UTF-8"?> <partial-response><redirect url="http://localhost:8080/test/login.jsp"></redirect></partial-response>
error[10:22:58.533]: Received 'error@malformedXML' event from <select id=alertTypeInfo:alertType ...>
error[10:22:58.595]: [200] undefined: undefined
Plz let me know if you have any solution for this issue.
Thanks & Regards
Ravi
-
10. Re: RF4: Session timeout, how?
ravi.jrk Apr 30, 2012 10:00 AM (in response to nbelaevski)HI,
Since We are using Spring security ,I have followed the below approach and it fixed the problem.
But the issue now is with SSO time out.
Assume SSO session is timed out, application session is still active, Now if the user is performed any ajax request then SSO will interfere and tries to redirect to SSO login page. Ajax is unable to parse sso repsone and it becomes unresponsive on the page.
Following exception is observed on a4j:log.
error[09:41:58.012]: Received 'error@malformedXML' event from<div id=dashboardForm:j_id168847210_1_7848f560:1 class=rf-tr-nd rf-tr-nd-colps ...>error[09:41:58.013]: [200] undefined: undefinedAny solutions/leads will be appreciated.
Thanks Ravi