PrimeFaces look'n'feel disappears when using Shiro - jsf-2

I use Primefaces 4.0 and Shiro 1.2.2 in a website that I currently developed.
My forms are interpreted and Primefaces components are displayed without problem. But when I enable the security on my application, my forms, at least login page, don't displays ​​with Primefaces rendering. I know that Shiro has intercepted all HTTP requests in order to control the access but why my form appears as if I did't use Primefaces? Please, do you have an idea of ​​solution to my problem? Is it possible to integrate Shiro and Primefaces?
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<resource-ref>
<res-ref-name>connectionPool</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>redmond</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
</web-app>
shiro.ini:
[main]
authc.loginUrl = /faces/login.xhtml
authc.usernameParam = login:username
authc.passwordParam = login:password
authc.rememberMeParam = login:rememberMe
user.loginUrl = /faces/login.xhtml
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
# Configure JDBC realm password hashing.
redentialsMatcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher
credentialsMatcher.hashAlgorithmName = SHA-256
jdbcRealm.credentialsMatcher = $credentialsMatcher
# Configure JDBC realm SQL queries.
jdbcRealm.authenticationQuery = SELECT password FROM USER WHERE username = ?
dbcRealm.userRolesQuery = SELECT role FROM ROLE WHERE userId = (SELECT id FROM USER WHERE username = ?)
# Configure JDBC realm datasource. DataSource properties
dataSource = org.apache.derby.jdbc.ClientDataSource
dataSource.serverName = localhost
dataSource.portNumber = 1527
dataSource.databaseName = testdb
dataSource.user = admin
dataSource.password = admin
jdbcRealm.dataSource = $dataSource
[users]
admin = password
[urls]
/faces/login.xhtml = authc
/faces/** = authc
I'm a beginner in web development with JSF, Primefaces and Shiro.
Thanks for your help.

Here in the last entry,
[urls]
/faces/login.xhtml = authc
/faces/** = authc
you've told Shiro to authenticate every single unmapped URL matching /faces/**. This thus also covers JSF resources such as CSS/JS/image files which are auto-included by JSF components (as in PrimeFaces). In effects, when the browser wants to download e.g. the CSS file, it receives a login page instead of the actual CSS content and is hence unable to apply the definied CSS styles. You can see it yourself by entering the URL to the CSS file in the browser's address bar yourself. Instead of the CSS file content, you'll see a login page. The webbrowser is "under the covers" facing exactly that problem.
You need to explicitly tell Shiro to allow unauthenticated (anonymous) access to JSF resources. Those resources are identified by an additional /javax.faces.resource path (as definied by the ResourceHandler#RESOURCE_IDENTIFIER constant in JSF API).
[urls]
/faces/login.xhtml = authc
/faces/javax.faces.resource/** = anon
/faces/** = authc
See also:
Apache Shiro in JSF2 tutorial - Restriction in HTTP requests

Related

serving common html without facelets/jsf-tags

I have the folder containing a client-side-html-template ("template.xhtml"). The folder resides in public folder (not in WEB_INF).
When saved the file with suffix "xhtml" and wrap the content with "<ui:composition", then client side (ajax) request can access.
However, when I save it to "template.html" and delete the "<ui:composition", then client ajax cannnot access this page (401).
My web.xml has this mapping:
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<mime-mapping>
<extension>xhtml</extension>
<mime-type>text/html</mime-type>
</mime-mapping>
<security-constraint>
<display-name>Restrict raw XHTML Documents</display-name>
<web-resource-collection>
<web-resource-name>XHTML</web-resource-name>
<url-pattern>*.xhtml</url-pattern>
</web-resource-collection>
<auth-constraint />
</security-constraint>
How can I serve common "html-files" by client side ajax request without intercepting these files by jsf/facelets?
Found a simple way without the need to change web.xml:
I changed the static "html" files to "htm".

index.html change to index.xhtml

When trying to logout my application I'm having the following error message :
com.sun.faces.context.FacesFileNotFoundException: /index.xhtml Not Found in ExternalContext as a Resource
To logout I'm going though the following steps inside PhaseListener.beforePhase(PhaseEvent phaseEvent) :
// Redirect to index.html
NavigationHandler nh = fctx.getApplication().getNavigationHandler();
String action_outcome = "/index.html";
nh.handleNavigation(fctx, null, action_outcome);
My web.xml is as follow :
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID"
version="3.0">
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<filter-mapping>
<filter-name>Seam Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>trinidad</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.seam</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<security-constraint>
<display-name>Restrict raw XHTML Documents</display-name>
<web-resource-collection>
<web-resource-name>XHTML</web-resource-name>
<url-pattern>*.xhtml</url-pattern>
</web-resource-collection>
<auth-constraint/>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
</web-app>
I do not have index.xhtml in my app, but I do have and want to keep it index.html file.
Why is my outcome_action given to NavigationHandler rename to index.xhtml ?
How could I avoid it ?
The NavigationHandler expects a JSF page, not a non-JSF page. Moreover, you're there actually not sending a real redirect at all, on the contrary to what the code comment says there. You're just performing a forward here.
Performing a real redirect would be the solution to your problem. It's to be done as below:
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.redirect(ec.getRequestContextPath() + "/index.html");
See also:
What is the difference between redirect and navigation/forward and when to use what?
How to navigate in JSF? How to make URL reflect current page (and not previous one)
Unrelated to the concrete problem, doing authorization job in a phase listener stinks. Have you considered a servlet filter?
See also:
Limitations of using a PhaseListener instead of a Servlet Filter for authorization
Failing to redirect from JSF phaselistener
How to invalidate session in JSF 2.0?

JSF tags not rendered after filter implementation

I was working on a project that worked fine until I decided to implement filtering.
I followed BalusC's post on JSF HTTP Session Login .
Now, none of the jsf tags is rendered. Here is my web.xml file
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<filter>
<filter-name>UserFilter</filter-name>
<filter-class>servlet.UserFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UserFilter</filter-name>
<url-pattern>/faces/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>ImageServlet</servlet-name>
<servlet-class>servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ImageServlet</servlet-name>
<url-pattern>/ImageServlet</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/admin/login.xhtml</welcome-file>
</welcome-file-list>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>blitzer</param-value>
</context-param>
When I remove the filters everything works fine.
That answer was based on FacesServlet mapping of *.xhtml. However, you've there the old JSF 1.0/1.1 style mapping of /faces/*. In other words, the FacesServlet is never invoked and you was just seeing the consequences.
You've 2 options:
Fix the filter to redirect to an URL matching your FacesServlet mapping.
res.sendRedirect(req.getContextPath() + "/faces/login.xhtml");
Change the FacesServlet mapping to *.xhtml like every sane JSF 2.x developer would do. This saves you from fiddling with virtual URLs all time.
See also:
JSF Facelets: Sometimes I see the URL is .jsf and sometimes .xhtml. Why?
JSF returns blank/unparsed page with plain/raw XHTML/XML/EL source instead of rendered HTML output
Unrelated to the concrete problem, if you intend to let the filter hook on a specific servlet, you'd better not copy its URL pattern like below:
<filter-mapping>
<filter-name>UserFilter</filter-name>
<url-pattern>/faces/*</url-pattern>
</filter-mapping>
Instead, you'd better map to the servlet name directly:
<filter-mapping>
<filter-name>UserFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
And, it would also be nice if you followed Java variable naming conventions in filter and servlet names:
<filter-name>userFilter</filter-name>
...
<servlet-name>facesServlet</servlet-name>
Think of it as if you're doing like this:
UserFilter userFilter = new UserFilter();

Primefaces 4, Omnifaces 1.7 JSF handle session timeout fail

faces-config.xml
<factory>
<exception-handler-factory>org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory</exception-handler-factory>
</factory>
web.xml
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/Login/login.xhtml</location>
</error-page>
<session-config>
<session-timeout>1</session-timeout>
</session-config>
<filter>
<filter-name>facesExceptionFilter</filter-name>
<filter-class>org.omnifaces.filter.FacesExceptionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>facesExceptionFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
After a session timeout i want to be redirectet to the login page. I use Form based authentication. When i login wait one minute and then hit a button i often get the following page:
error page:
<partial-response id="j_id1">
<redirect url="/CuViS/Manager/show.xhtml"/>
<changes>
<update id="j_id1:javax.faces.ViewState:0">-2290296337409893276:-7107311277476366039</update>
</changes>
</partial-response>
Where the url is the current page where i clicked the button.
When i remove the omnifaces configuration the same behavior appears. What I am doing wrong?

Tomahawk JSCookMenu does not trigger any actions after upgrading to JSF2

I've just migrated some medium-size web application from JSF 1.2/MyFaces to JSF 2.0/Mojarra. Apart from some custom components that I've implemented, everything seems to work, except for the JSCookMenu from Tomahawk (yes, I have Tomahawk which is a library from Apache, and still want to use Mojarra - but I understood there shouldn't be any big problem). I've replaced the myfaces-api.jar and myfaces-impl.jar with the corresponding jsf-api.jar and jsf-impl.jar, and took out from web.xml as many MyFaces parameters and filters as possible (some needed to remain because I still use Tomahawk). I have also upgraded Tomahawk to 1.1.11 for JSF2.
The application's JSCookMenu renders just fine, but doesn't trigger any action when clicking the menu items. I have some t:navigationMenuItem whose action attribute is bound to an outcome in faces-config.xml which should load a new view id, and yet some t:navigationMenuItem whose actionListener attribute is bound to a bean method (the Logout menu item, for example). Neither of them works, the actionListener code from my bean is not even called.
I'm not even sure how to investigate this, did anybody have a clue as to how can this be solved? I'm hoping something in web.xml can be of help.
The navigation cases are written correctly in the faces-config.xml, they used to work on JSF 1.2/MyFaces and also on JSF 2/MyFaces prior to the migration to Mojarra.
This is the relevant part of my web.xml file:
<servlet>
<servlet-name>faces</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>faces</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<context-param>
<param-name>com.sun.faces.allowTextChildren</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name>
<param-value>com.avalanche.jsf.MyResourceResolver</param-value>
</context-param>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.AUTO_SCROLL</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>facelets.RECREATE_VALUE_EXPRESSION_ON_BUILD_BEFORE_RESTORE</param-name>
<param-value>false</param-value>
</context-param>
<filter>
<filter-name>facesExtensionsFilter</filter-name>
<filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
<init-param>
<param-name>uploadMaxFileSize</param-name>
<param-value>1g</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>facesExtensionsFilter</filter-name>
<servlet-name>faces</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>facesExtensionsFilter</filter-name>
<url-pattern>/faces/myFacesExtensionResource/*</url-pattern>
</filter-mapping>

Resources