Developing web application in Java EE with JSF. All pages are secured from viewing by authentication form with action 'j_security_check' and inputs 'j_username' and 'j_password'.
After successful log in, however, I am redirected not to the page I wanted to access but to this URL
/faces/javax.faces.resource/jsf.js?ln=javax.faces&stage=Development
So I'm looking at the script file jsf.js with all the JS code instead of the page I wanted to view. It doesn't matter if I access the web root or any other page, I'm being redirected to this URL every time. Then I change the URL to any page, it loads it fine and I am logged in.
I have to say I already had this problem which magically went away so it redirected me correctly. After few weeks it got broken again but I don't if it was my fault, and if it was I don't know the cause. I wasn't messing with redirect or navigational rules at all.
Good to mention that I'm also using PrettyFaces.
EDIT:
<security-constraint>
<display-name>secured</display-name>
<web-resource-collection>
<web-resource-name>all</web-resource-name>
<description/>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>admin</role-name>
<role-name>teacher</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<display-name>secured for admins</display-name>
<web-resource-collection>
<web-resource-name>admin pages</web-resource-name>
<description/>
<url-pattern>/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<display-name>unsecured</display-name>
<web-resource-collection>
<web-resource-name>css</web-resource-name>
<description/>
<url-pattern>/css/*</url-pattern>
</web-resource-collection>
<web-resource-collection>
<web-resource-name>js</web-resource-name>
<description/>
<url-pattern>/js/*</url-pattern>
</web-resource-collection>
<web-resource-collection>
<web-resource-name>img</web-resource-name>
<description/>
<url-pattern>/img/*</url-pattern>
</web-resource-collection>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>wetk-security</realm-name>
<form-login-config>
<form-login-page>/faces/login.xhtml</form-login-page>
<form-error-page>/faces/login.xhtml</form-error-page>
</form-login-config>
</login-config>
The container managed security will redirect to the last HTTP request which triggered the authentication check. In your case it's apparently the auto-included JSF ajax API JavaScript file. That can happen if the browser has loaded the to-be-authenticated page fully from the browser cache, while the browser has loaded the JS file fully from the server side, or have tested the cache validity of the JavaScript file by a conditional GET request.
You'd like to exclude the JSF resources (<h:outputScript>
, <h:outputStylesheet>
and <h:graphicImage>
from authentication checks. You could do that by excluding the common URL pattern /javax.faces.resource/*
. You may only want to add the /faces
prefix pattern as you're apparently using it instead of the *.xhtml
suffix pattern.
You also need to instruct the browser to not cache restricted pages to prevent the browser loading it from the cache (e.g. by pressing back button after logout). Map the following filter on the same URL pattern as the one of your <security-constraint>
.
@WebFilter("/secured/*") // Use the same URL pattern as <security-constraint>
public class NoCacheFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) request;
HttpServletResponse httpRes = (HttpServletResponse) response;
if (!httpReq.getRequestURI().startsWith(httpReq.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
httpRes.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
httpRes.setHeader("Pragma", "no-cache"); // HTTP 1.0.
httpRes.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(request, response);
}
// ...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With