Mutant Mumblings

Monday Oct 08, 2007

Using Acegi with JSF and Facelets

A few months ago I was having a hard time getting Facelets and Acegi working properly together. In the past I had gotten JSF+JSP to work with acegi following a great article over at the MyFaces Wiki, but replacing JSP with Facelets causes a few new issues that must be resolved.

All the screen setup should be exactly the same as the MyFaces wiki suggests, but the navigation rules is going to need a little work:

In faces-config.xml

<navigation-rule>
  <from-view-id>/login.xhtml</from-view-id>
  <navigation-case>
    <from-outcome>login</from-outcome>
    <to-view-id>/j_acegi_security_check.jsp</to-view-id>
  </navigation-case>
</navigation-rule>

Notice that the from-view-id has been changed to a xhtml extension, but the to-view-id remains jsp. At first I was trying to get the rule to work with the to-view-id set with a .xhtml extension, but this has one major issue:

  • When processing navigation rules to a new facelet, there is no servlet forward like there would be with JSPs(facelets are not servlets). So there is no chance for the Acegi filter chain to fire.

However, just switching to the .jsp extension is not enough, by default faclets wants to believe that all navigation rules will only refer to facelets. So by default, even with the above rule, facelets tries to parse a file called "j_acegi_security_check.xhtml". But this is easy to solve once your know the problem.

In web.xml:

<context-param>
   <param-name>facelets.VIEW_MAPPINGS</param-name>
   <param-value>*.xhtml</param-value>
</context-param>

This tells facelets that only navigation rules with to-view-ids that end in ".xhtml" should be treated as facelets and everything else should be deferred back to the default view handler. This allows "/j_acegi_security_check.jsp" to be seen as something outside of facelets and causes a servlet forward to occur.

But there is still one catch. Even though your navigation rule tells JSF to forward onto "/j_acegi_security_check.jsp", the forward request actually says "/j_acegi_security_check.xhtml". So you will need to update your Acegi spring configuration to tell the AuthenticationProcessingFilter to look somewhere else instead:

In applicationContext-security.xml:

<property name="filterProcessesUrl" value="/j_acegi_security_check.xhtml" />

The inconsistency between the navigation rule and the filterProcessesUrl still drives me nuts, but this solution does work and is very simple to implement.

Updates - 4/15/2008

Kace's and Vadus's comments below actually point out an assumption I made when originally writing this article. I assumed that the JSF servlet was mapped to .xhtml(like in the MyFaces wiki) If its not, like in the case of Kace and Vadus, your filterProcessUrl needs to be /j_acegi_security_check.[extension that JSF servlet is mapped to]. In Kace's case it should be mapped to ".html" and in Vadus's case its mapped as ".jsf". However, unless you have a compelling case not to, I would try to always map the faces servelt to .xhtml just for the added benefit that people will not be able to manually navigate to your .xhtml pages (no need to add extra security rules)

Calendar

Feeds

Search

Links

Navigation