javakaffee

Just another weblog about (web) development technologies like spring, tapestry, jersey, jsf, hibernate and more

July 4, 2006

JSF/Acegi authentication with a backing bean

Filed under: development, java, security — martin.grotzke @ 10:40 am

Thanx to this blog post i managed to integrate Acegi 1.0.1 with JSF. Some minor modifications were necessary, because in this version of Acegi some things have changed.

The basic idea of this approach is to use a JSF backing bean that is responsible for authentication (that processes the “login” request from the user). This allows you not only to send the user to a success/error page, but you are also able to send him to a custom page if some condition is met.

The backing bean looks like the following:


package com.freiheit;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationManager;
import org.acegisecurity.context.HttpSessionContextIntegrationFilter;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.acegisecurity.ui.WebAuthenticationDetails;
import org.acegisecurity.ui.webapp.AuthenticationProcessingFilter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Required;

public final class AuthenticationController {

 private static final Log LOG = LogFactory.getLog( AuthenticationController.class );

 private String _username;
 private String _password;

 // injected properties
 private AuthenticationManager _authenticationManager;

 public String getPassword() {
     return _password;
 }

 public void setPassword( String password ) {
     _password = password;
 }

 public String getUsername() {
     return _username;
 }

 public void setUsername( String userName ) {
     _username = userName;
 }

 @SuppressWarnings("unchecked")
 public String authenticate() {
     String outcome = "failure";

     try {
         final String userName = getUsername();
         final String password = getPassword();
         final UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(
                 userName, password );

         final HttpServletRequest request = getRequest();
         authReq.setDetails( new WebAuthenticationDetails( request ) );

         final HttpSession session = request.getSession();
         session.setAttribute(
                         AuthenticationProcessingFilter.ACEGI_SECURITY_LAST_USERNAME_KEY,
                         userName );

         /* perform authentication
          */
         final Authentication auth = getAuthenticationManager().authenticate( authReq );
      
         /* initialize the security context.
          */
         final SecurityContext secCtx = SecurityContextHolder.getContext();
         secCtx.setAuthentication( auth );
         session.setAttribute( HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, secCtx );
      
         outcome = "success";
      
     } catch ( Exception e ) {
         outcome = "failure";
         FacesContext.getCurrentInstance().addMessage( null, new FacesMessage( e.getMessage() ) );
     }
  
     return outcome;
 }

 public void logout( ActionEvent e ) {

     final HttpServletRequest request = getRequest();
     request.getSession( false ).removeAttribute( HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY );
  
     /* simulate the SecurityContextLogoutHandler
      */
     SecurityContextHolder.clearContext();
  
     request.getSession( false ).invalidate();
 }

 private HttpServletRequest getRequest() {
     return (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
 }

 public AuthenticationManager getAuthenticationManager() {
     return _authenticationManager;
 }

 @Required
 public void setAuthenticationManager(
         AuthenticationManager authenticationManager ) {
     _authenticationManager = authenticationManager;
 }

}


The spring configuration (applicationContext.xml) has the following entries (note that this is spring-2, this introduces new scopes like e.g. “session”):


 <bean id="acegiFilterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
  <property name="filterInvocationDefinitionSource">
   <value>
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /**=httpSessionContextIntegrationFilter,securityRequestFilter,exceptionTranslationFilter,filterSecurityInterceptor
   </value>
  </property>
  <!-- 
   /**=httpSessionContextIntegrationFilter,requestWrapper,filterSecurityInterceptor
  -->
 </bean>
 
 <bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">
  <property name="context">
   <value>org.acegisecurity.context.SecurityContextImpl</value>
  </property>
 </bean>
 
 <bean id="securityRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter" />
 
 <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
  <property name="authenticationEntryPoint">
   <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
    <property name="loginFormUrl">
     <value>/login.jsf</value>
    </property>
    <property name="forceHttps"><value>false</value></property>
   </bean>
  </property>
  <property name="accessDeniedHandler">
   <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
    <property name="errorPage">
     <value>/accessDenied.jsf</value>
    </property>
   </bean>
  </property>
 </bean>
 
 <bean id="filterSecurityInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
  <property name="authenticationManager"><ref bean="authenticationManager"/></property>
  <property name="accessDecisionManager">
   <!--
    The AffirmativeBased voter allows access if at least one voter votes
    to grant access. Use the UnanimousBased voter if you only want to
    grant access if no voter votes to deny access. -->
   <bean class="org.acegisecurity.vote.AffirmativeBased">
    <property name="decisionVoters">
     <list>
      <bean class="org.acegisecurity.vote.RoleVoter">
       <!--  Reset the role prefix to "", default is ROLE_ -->
       <property name="rolePrefix">
        <value></value>
       </property>
      </bean>
      <!--
       The authenticated voter grant access if e.g.
       IS_AUTHENTICATED_FULLY is an attribute -->
      <bean class="org.acegisecurity.vote.AuthenticatedVoter" />
     </list>
    </property>
   </bean>
  </property>
  <property name="objectDefinitionSource">
   <value>
    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /pages/**=IS_AUTHENTICATED_FULLY
    /pages/company/**=/permissions/permission1
    /pages/**=/permissions/permission01
   </value>
  </property>
 </bean> 

 <bean id="authenticationManager"
  class="org.acegisecurity.providers.ProviderManager">
  <property name="providers">
   <list>
    <ref local="daoAuthenticationProvider" />
   </list>
  </property>
 </bean>
 
 <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
  <property name="userDetailsService">
   <bean class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
    <property name="userMap">
     <value>
      mgrotzke=test123,/permissions/permission1,/permissions/permission01
      skaiser=test123,/permissions/permission01
     </value>
    </property>
   </bean>
  </property>
 </bean>
 
 <bean id="authenticationController" class="com.freiheit.AuthenticationController" scope="session">
  <property name="authenticationManager"><ref bean="authenticationManager"/></property>
 </bean>


The authenticationController bean is the backing bean (see above) that is called from the (jsp/facelets) page. It can be defined in the spring applicationContext.xml because the faces-config contains an entry for springs DelegatingVariableResolver:


     <application>
        <variable-resolver>
            org.springframework.web.jsf.DelegatingVariableResolver
        </variable-resolver>
    </application>


The web.xml has the following filter entry for acegi:


 <filter>
  <filter-name>Acegi Filter Chain Proxy</filter-name>
  <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
  <init-param>
   <param-name>targetBean</param-name>
   <param-value>acegiFilterChainProxy</param-value>
  </init-param>
 </filter>

 <filter-mapping>
      <filter-name>Acegi Filter Chain Proxy</filter-name>
      <servlet-name>Faces Servlet</servlet-name>
      <dispatcher>FORWARD</dispatcher>
      <dispatcher>REQUEST</dispatcher>
  </filter-mapping>


The faces-config.xml contains the following navigation-rules for login and logout:


<navigation-rule>
 <from-view-id>/login.xhtml</from-view-id>
 <navigation-case>
  <from-action>#{authenticationController.authenticate}</from-action>
  <from-outcome>success</from-outcome>
  <to-view-id>/pages/index.xhtml</to-view-id>
  <redirect/>
 </navigation-case>
 <navigation-case>
  <from-action>#{authenticationController.authenticate}</from-action>
  <from-outcome>failure</from-outcome>
  <to-view-id>/login.xhtml</to-view-id>
 </navigation-case>
</navigation-rule>
<navigation-rule>
 <from-view-id>*</from-view-id>
 <navigation-case>
  <from-action>logout</from-action>
  <to-view-id>/login.xhtml</to-view-id>
  <redirect/>
 </navigation-case>
</navigation-rule>


The login page using facelets essentially has the following content:


<form jsfc="h:form" id="loginForm">
 <span jsfc="h:messages"/><br/>
 Username: <input jsfc="h:inputText" id="inputUsername" value="#{authenticationController.username}" /><br/>
 Password: <input jsfc="h:inputSecret" value="#{authenticationController.password}" /><br/>
 <input jsfc="h:commandButton" action="#{authenticationController.authenticate}"
     value="Login" />
</form>


The logout button should be defined in an overall template, and would look like the following:


<a href="#" jsfc="h:commandLink" action="logout"
    actionListener="#{authenticationController.logout}">#{msgs.logout}</a>

91 Comments »

  1. Can’t you just post the WHOLE example ? The little fragments just won’t help much :( Maybe you can post the JSP page, etc. That will save us a lot of time, otherwise we spend quite sometime trying to understand the solution…
    Thanks in advance…

    Comment by Anonymous — August 23, 2006 @ 7:40 pm

  2. Hello, i just added the relevant parts of the faces-config.xml and the login page, additionally an example for a logout-button.

    Notice that the logout method changed from an action method (String logout()) to an actionlistener (void logout(ActionEvent e)).

    I hope this helps,
    cheers,
    Martin

    Comment by Martin Grotzke — August 23, 2006 @ 10:13 pm

  3. The bean filterSecurityInterceptor requires the additional decisionVoter org.acegisecurity.vote.AuthenticatedVoter so that s.th. like /pages/**=IS_AUTHENTICATED_FULLY can be specified in the objectDefinitionSource. Example is updated accordingly.

    Comment by martin.grotzke — September 14, 2006 @ 6:03 pm

  4. Hi Martin,

    wanna thank you for your email support. I got it running.

    Suggestion:
    I had some problems with the labels that are used. As I mixed your code with another example for acegi method access security, e.g. the faces servlet label didn’t match. Would be nice to get complete examples of faces-config.xml, applicationContext.xml and web.xml. A full deployable example would be even better ;-).

    Regards Rainer

    Comment by Rainer Eschen — September 20, 2006 @ 11:50 am

  5. Hey Rainer,

    thank you for your feedback!
    I tried to extract the relevant parts, so that one is not distracted by less important things. Although, if there’s a dependency on the Faces Servlet name then it should be mentioned. I’ll update the example soon.

    Cheers,
    Martin

    Comment by martin.grotzke — September 20, 2006 @ 12:29 pm

  6. Interesting information concerning forwards was just posted in the myfaces mailinglist:
    http://www.mail-archive.com/users@myfaces.apache.org/msg28125.html

    I’ll check if this has to be applied to this example.

    Comment by martin.grotzke — September 21, 2006 @ 2:39 pm

  7. As posted by Dmitry V. Zemnitskiy at http://magrokosmos.blogspot.com/2006/07/jsfacegi-authentication-with-backing.html i have missed to set the scope of the authenticationController bean in this example to scope="session". This is fixed now !

    Comment by martin.grotzke — September 22, 2006 @ 3:52 pm

  8. I’m not sure about that scope=”session”, don’t recall such an attribute for Spring’s app context.

    Anyway, I’m actually wondering how you’ve displayed the error messages on the login page. Adding a simple sufficed? I can’t seem to get the error message to appear though…

    Comment by David Lim — September 26, 2006 @ 9:42 am

  9. Hi David,

    new scopes are one of the new features of spring2, e.g. scopes request and session, see spring documentation.

    The error messages are displayed with a <span jsfc="h:messages"/> tag in the login.xhtml. Probably i should add this also to the example.

    Thanx for this hint,
    cheers,
    Martin

    Comment by martin.grotzke — September 26, 2006 @ 9:56 am

  10. Hi,

    Love your example, it got me going. I have one problem, however. The requests seem to “lag” by one; I login, but the next operation causes a new login and that second login then sticks. The same with logout. Any suggestions?

    Comment by Nik — November 8, 2006 @ 9:16 am

  11. Ehem, ignore my post, I did some changes and messed up my logout-navigation which resulted in something off-by-one with the filters…

    Comment by Nik — November 8, 2006 @ 9:51 am

  12. I tried to run the application. But my jsf file could not resolve the values which are coming from spring session scope bean. It is giving me error “Scope ’session’ is not active; nested exception is java.lang.IllegalStateException: thread-bound request: use RequestContextFilter”.

    Could you plz send me complete working code.

    Comment by Umesh Sinha — November 13, 2006 @ 3:52 pm

  13. Did you configure the spring RequestContextFilter correctly? I only showed web.xml entries that are relevant for acegi, asuming that all other stuff is set up already.
    What I have for spring in the web.xml:

    
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>/WEB-INF/applicationContext.xml</param-value>
    	</context-param>
    ...
    	<filter>
    		<filter-name>RequestContextFilter</filter-name>
    		<filter-class>
    			org.springframework.web.filter.RequestContextFilter
    		</filter-class>
    	</filter>
    ...
    	<filter-mapping>
    		<filter-name>RequestContextFilter</filter-name>
    		<servlet-name>Faces Servlet</servlet-name>
    	</filter-mapping>
    ...
    	<listener>
    		<listener-class>
    			org.springframework.web.context.ContextLoaderListener
    		</listener-class>
    	</listener>
    

    (Asuming that your faces servlet is named “Faces Servlet”).

    I’m off for holiday for the next two weeks, so don’t get it wrong if I’m not responding… ;)

    Cheers,
    Martin

    Comment by martin.grotzke — November 13, 2006 @ 5:36 pm

  14. […] JSF/Acegi authentication with a backing bean […]

    Pingback by Howto Secure JSF via Spring/Acegi at rain.webs Blog: Springsteam — November 14, 2006 @ 6:53 pm

  15. Hi Martin,

    I’m changing to session scope at the moment. During the deployment I got an exception, because the authenticationController is a final class. You may skip the final. This works with OC4J 10.

    Regards Rainer

    Comment by Rainer Eschen — November 15, 2006 @ 10:27 am

  16. Hi all,

    if you think about using your beans in a mixed Spring/JSF environment, asking when to use what (Spring bean vs. JSF managed bean), here are some hints:

    http://blog.rainer.eschen.name/2006/11/16/the-observer-pattern-in-mixed-dependency-injection-contexts-spring-jsf/

    Regards Rainer

    Comment by Rainer Eschen — November 17, 2006 @ 10:29 am

  17. I used your example to integrate acegi with jsf but I have a problem where my secured pages are being exposed when I don’t log in. Any help would be appreciated

    Comment by SpringLover — November 24, 2006 @ 7:03 am

  18. Check the property objectDefinitionSource of the bean with id filterSecurityInterceptor in the applicationContext.xml, it must have the entry with s.th. like /pages/**=IS_AUTHENTICATED_FULLY. Additionally you must have the AuthenticatedVoter in the list of decisionVoters.

    Do you have it like it is shown in this example?

    Cheers,
    Martin

    Comment by martin.grotzke — November 27, 2006 @ 5:41 pm

  19. yes, I was finally able to get this working by doing some digging into javadocs and finding that it needs an additional property

    false

    This did the trick.

    thanks for your valuable example

    Comment by SpringLover — November 28, 2006 @ 12:14 am

  20. Martin,
    I am running into a strange issue. Let me layout the scenario

    I have two secured pages

    /pages/page1.jsf
    /page/page2.jsf

    User A has access to view page1.jsf but not page2.jsf

    when user A clicks on page1.jsf he is directed to the login screen. Everything is good.

    Then when user A clicks on page2.jsf he does not get directed to the login screen but the browser just goes into an infinite loop.

    If this explanation is not clear please let me know

    Please let me know if you can be of assistance

    thanks

    Comment by SpringLover — November 29, 2006 @ 3:12 pm

  21. Hi SpringLover :)

    what is the location of the login screen?
    Can you post the objectDefinitionSource property?

    Cheers,
    Martin

    Comment by martin.grotzke — November 29, 2006 @ 4:35 pm

  22. /pages/project/addproject.jsp=ROLE_PW_APP_ADMIN,ROLE_PW_SUPERVISOR,ROLE_PW_INSPECTOR,ROLE_APPLICANT_ADMIN,ROLE_APPLICANT_USER,ROLE_DESIGN_ADMIN,ROLE_DESIGN_USER
    /pages/project/enforcement/enforcements.jsp=ROLE_PW_APP_ADMIN,ROLE_PW_SUPERVISOR,ROLE_PW_INSPECTOR
    /pages/project/correspondence/correspondence.jsp=ROLE_PW_APP_ADMIN,ROLE_PW_SUPERVISOR,ROLE_PW_INSPECTOR,ROLE_PW_REVIEWER
    /pages/admin/admin.jsp=ROLE_PW_APP_ADMIN,ROLE_APPLICANT_ADMIN,ROLE_ENGINEERING_ADMIN,ROLE_DESIGN_ADMIN,ROLE_GRADING_ADMIN
    /pages/admin/environment/**=ROLE_PW_APP_ADMIN
    /pages/admin/project/**=ROLE_APP_ADMIN
    /pages/admin/security/firms.jsp=ROLE_APP_ADMIN

    Comment by SpringLover — November 30, 2006 @ 6:57 am

  23. Okay, then where’s the login screen? Is it e.g. at /pages/login.jsf?

    I just tried to reproduce this behavior in our application but was not able to get this behavior.

    Can you debug the problem (server side debugging), step through (having sources of myfaces, acegi & co is very helpful) and determine the reason of this behavior?

    Or you could search/ask for help directly at acegi.

    Cheers,
    Martin

    Comment by martin.grotzke — November 30, 2006 @ 10:28 am

  24. the login page is /pages/login/login.jsp

    could you please send me your setup to look at it

    Comment by SpringLover — December 1, 2006 @ 4:42 pm

  25. Martin,
    Thanks for your help. It was my AccessDecisionHandler that was not configured correctly. It is working now

    Comment by SpringLover — December 2, 2006 @ 12:54 pm

  26. Great to hear that it’s working now :)

    Have fun, cheers,
    Martin

    Comment by martin.grotzke — December 3, 2006 @ 8:07 pm

  27. Here’s how to add remember services to the example above for anyone who’s interested. I will also add support for redirect to target url in a following post.

    [BLOG] refers to code fragments in this entry.
    [NEW] is added support for remember me services.

    [NEW] private RememberMeServices rememberMeServices; // injected
    [BLOG] ..
    [BLOG] session.setAttribute( HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY, secCtx );
    [NEW] rememberMeServices.loginSuccess(request, response, authResult);
    [BLOG] outcome = “success”;

    [BLOG] catch ( Exception e ) {
    [NEW] SecurityContextHolder.getContext().setAuthentication(null);
    [NEW] rememberMeServices.loginFail(request, response);
    [BLOG outcome = “failure”;

    spring.xml
    ———-

    Hung Tang

    Comment by Hung Tang — December 5, 2006 @ 9:27 pm

  28. Support for redirection to target path after successful login:

    
        public String redirectTargetUrl(HttpServletRequest request) {
            final String targetUrl = AbstractProcessingFilter.obtainFullRequestUrl(request);
            if (targetUrl == null) return "defaultUrl";
            logger.info("Target Url: [" + targetUrl + "]");
    
            final String contextPath = request.getContextPath();
            final int idx = targetUrl.indexOf(contextPath);
            final String viewId = targetUrl.substring(idx + contextPath.length());
    
            logger.info("ViewId: [" + viewId + "]");
            final ViewHandler viewHandler = getApplication().getViewHandler();
            UIViewRoot viewRoot = viewHandler.restoreView(getFacesContext(), viewId);
            if (viewRoot == null) {
                viewRoot = viewHandler.createView(getFacesContext(), viewId);
                viewRoot.setViewId(viewId);
                getFacesContext().renderResponse();
            }
            getFacesContext().setViewRoot(viewRoot);
            request.getSession(false)
                    .removeAttribute(AbstractProcessingFilter.ACEGI_SAVED_REQUEST_KEY);
            return null;
        }
        
    
        /insert login page here
        
    	defaultUrl
    	/insert redirect page here
        
    

    Comment by Hung Tang — December 5, 2006 @ 9:30 pm

  29. spring.xml got cut off from first entry, hopefully this goes through.

    
    spring.xml
    ----------
    
    <bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
        <property name="userDetailsService" ref="userDetailsService"/>
        <property name="key" value="changeThis"/>
    </bean>
    
    <bean id="authenticationProcessingFilter"
              class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
        ...
        <property name="rememberMeServices" ref="rememberMeServices"/>
    </bean>
    
    <bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
        ...
        <property name="rememberMeServices" ref="rememberMeServices"/>
    </bean>
    
    <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
        <!-- URL to redirect when logout is successful -->
        <constructor-arg value="/"/>
        <constructor-arg>
            <list>
       	    <!-- removes cookie when logging out -->
    	    <ref bean="rememberMeServices"/>
    	    <!-- SecurityContextHolder.clearContext() -->
    	    <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
        </list>
        </constructor-arg>
        <!-- URL for invoking this filter -->
        <property name="filterProcessesUrl" value="/signout.jsf"/>
    </bean>
    
    

    faces-config.xml got cut off for second entry. trying again…

    /insert login page here

    defaultUrl
    /insert redirect page here

    [/code]

    Comment by Hung Tang — December 5, 2006 @ 9:36 pm

  30. /insert login page here

    defaultUrl
    /insert redirect page here

    Sorry, I am amateur at using quicktags. Hopefully the author can clean up my mess…and put all this extra info together. Hope others can benefit from it.

    Comment by Hung Tang — December 5, 2006 @ 9:40 pm

  31. Hello Hung,

    just saw your comments, they seem to be very interesting…
    Having just a short look, I don’t get the meaning of the “/insert login page here” etc. stuff, but when I have more time I’ll think about it ;)

    Thanx && cheers,
    Martin

    Comment by martin.grotzke — December 6, 2006 @ 1:42 am

  32. Martin,

    I am trying to insert a piece of fragment from faces-config.xml but the blog software is “snipping” them off. Let me try again.

    
        <navigation-rule>
            <from-view-id>/insert login page here</from-view-id>
            <navigation-case>
                <from-outcome>defaultUrl</from-outcome>
                <to-view-id>/insert default target url to redirect here</to-view-id>
            </navigation-case>
        </navigation-rule>
    

    Comment by Hung Tang — December 6, 2006 @ 6:39 pm

  33. Hello Hung,

    I just added a

    <pre>

    tag before the

    <code>

    tag, then it worked.

    Cheers,
    Martin

    Comment by martin.grotzke — December 7, 2006 @ 10:12 am

  34. Hung, can you please upload a complete example of this redirect? I can’t seem to get it working and desperately need this functionality.

    Comment by Mick Knutson — March 5, 2007 @ 11:54 pm

  35. Email me at [mail(at)hungtang.com] and I’ll see what I can do.

    Comment by Hung Tang — March 7, 2007 @ 10:56 pm

  36. I’ve gotten this to work successfully except for JSF it processes on the request uri instead of the view ID.
    So if you go from a login page to a page in admin directory your admin home page won’t get authenticated because the first request doesn’t have /admin/ in it. However if you go to another page in the directory the next path will have the path in it. I will attempt to look at the view id instead of the uri to apply security in the filter.
    I’ve done this in the past so shouldn’t be too extremeley hard.

    Shawn

    Comment by Shawn Garner — March 11, 2007 @ 7:27 pm

  37. Hi,
    I tried your code and have made all the neccessary changes but couldn’t get it running. The problem is whenver I submit the login form I am being directed to the Error.jsp that I have designed. Can you help me please. Thanks!

    Comment by carp — March 12, 2007 @ 10:38 am

  38. Hi Carp,

    are you speaking of the RememberMeServices of Hung? Then he would have to help you.
    Do you have any logging output that you could post? Are you sure that authentication was successful?

    Cheers,
    Martin

    Comment by martin.grotzke — March 12, 2007 @ 10:50 am

  39. Hi Martin,
    Thanks a lot for your reply.
    No, its not the rememberMe services. The problem is with:
    Authentication auth = getAuthenticationManager().authenticate(authReq);
    The authenticationManager is not getting populated.
    If you don’t mind I would like to send my piece(Acegi and JSF part) of code to you. Please let me know your mail-id.

    Thanks & Regards,
    Carp.

    Comment by carp — March 12, 2007 @ 12:35 pm

  40. Hey Carp,

    what do you mean with “is not getting populated”?

    Feel free to send your code, I just sent you my email address.

    Cheers,
    Martin

    Comment by martin.grotzke — March 12, 2007 @ 1:03 pm

  41. Hey Martin,
    I didn’t get ur mail-id.
    Please send it to: qt_23@sifymail.com

    Thanks & Regards,
    Carp.

    Comment by Carp — March 12, 2007 @ 1:33 pm

  42. Hi Martin,
    I didn’t get your email address. Anyways here is my piece of code.
    I am using the same AuthenticationController.java as presented on this blog.

    This is what I have as my Login Page:

    
    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
    
    <html>
    	<head>
        	<title> PURCHASE PROCESS </title>
     	</head>
    	<body>
        	<f:view>
         	<center>
          	<h:form>
            <h1>	<h:outputText value="PURCHASE PROCESS"/> <br><br></h1>     
           	<p>		<h:messages style="color: blue"/>	</p><p> 
           	
            <h:outputText value="Username"></h:outputText> 
            <h:inputText id="username" value="#{authenticationController.username}" required="true"> 
            	<h:message for="username"></h:message>       
            </h:inputText>
            <br></p><p>&nbsp;
            <h:outputText value="Password"/>
            
            <h:inputSecret id="Password" redisplay="true" value="#{authenticationController.password}" required="true"/>
               	
     		<br><h:commandButton id="logon" value="SUBMIT" action="#{authenticationController.authenticate}"/> 
        
          	</h:form>
          	</center>
        	</f:view>
    	</body>
    </html>
    
    
    Here is the part of faces-config.xml:
    
    <navigation-rule>
    	<from-view-id>/Login.jsp</from-view-id>
     	<navigation-case>
      		<from-action>#{authenticationController.authenticate}</from-action>  
      		<from-outcome>success</from-outcome>
      	<to-view-id>/Menu.jsp</to-view-id>
      	<redirect/>
    	</navigation-case>
    	<navigation-case>
      		<from-action>#{authenticationController.authenticate}</from-action>  
      		<from-outcome>failure</from-outcome>
      	<to-view-id>/Error.jsp</to-view-id>
      	<redirect/>
    	</navigation-case>
    </navigation-rule>
    
    <managed-bean>
        	<managed-bean-name>authenticationController</managed-bean-name>
        	<managed-bean-class>com.i3l.ppsapplication.handler.AuthenticationController</managed-bean-class>
        	<managed-bean-scope>session</managed-bean-scope>
    </managed-bean> 
    
    This is part of applicationContext.xml:
    
    <bean id="authenticationController" 
    	class="com.i3l.ppsapplication.handler.AuthenticationController" scope="session">
    	<property name="authenticationManager">
    		<ref bean="authenticationManager"/>
    	</property>
    </bean>
    
    <bean id="authenticationManager"
    	class="org.acegisecurity.providers.ProviderManager">
    	<property name="providers">
    		<list>
    			<ref bean="daoAuthenticationProvider"/>
    			<ref bean="anonymousAuthenticationProvider"/>
    			ref bean="rememberMeAuthenticationProvider"/>								
    		</list>
    	</property>
    </bean>
    
    

    Comment by carp — March 12, 2007 @ 2:18 pm

  43. I can’t see anything wrong in your code snipplets. And your autenticationController returns “success” as outcome?

    Can you also post the objectDefinitionSource property of the filterSecurityInterceptor in your applicationContext.xml?

    Cheers,
    Martin

    Comment by martin.grotzke — March 13, 2007 @ 12:04 am

  44. Hi Martin,

    I have got it working now. Thanks for your support.
    The problem was that I had not added the following property to my bean in faces-config.xml:

    authenticationManager
    #{authenticationManager}

    What a relief!

    ;)Cheers,
    Carp

    Comment by carp — March 13, 2007 @ 10:46 am

  45. Good that it’s working now :)

    Cheers,
    Martin

    Comment by martin.grotzke — March 13, 2007 @ 11:01 am

  46. Hi Martin,

    When I run Menu.jsp page directly without Authenticating the ExceptionTranslationFilter should spawn the Login page for me as defined in the AuthenticationEntryPoint but its not happening. I am getting an error: org.apache.jasper.JasperException: Cannot find FacesContext

    My objectDefinitionSource is:

    
    <property name="objectDefinitionSource">
    <value>
          CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
          PATTERN_TYPE_APACHE_ANT
          /admin/**=ROLE_ADMINISTRATOR
          /menu.jsp=ROLE_REQUESTER
          /login.jsp=ROLE_ANONYMOUS
    </value>
    </property>
    

    Comment by carp — March 14, 2007 @ 8:46 am

  47. Hi Carp,

    does this also happen when you request some page at /admin/… ?

    We moved all secured pages to /pages/ and added /pages/**=IS_AUTHENTICATED_FULLY to the
    objectDefinitionSource to make sure that these pages are accessed by authenticated
    users only (you need the AuthenticatedVoter for this).

    Can you try to put the menu.jsp to s.th. like /pages/menu.jsp or some other subfolder and test if the error then also occurrs?
    Or can you try the IS_AUTHENTICATED_FULLY configuration and see if this changes s.th.?
    Otherwise I’d debug and step through the acegi code to see what happens…

    Cheers,
    Martin

    Comment by martin.grotzke — March 14, 2007 @ 11:06 am

  48. Hi,
    Thanks very much for posting this. I am trying to use it with MyFaces and am getting the following exception:
    Exception starting filter Acegi Filter Chain Proxy
    java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
    at org.springframework.web.context.support.WebApplicationContextUtils.getRequiredWebApplicationContext(WebApplicationContextUtils.java:86)
    at org.acegisecurity.util.FilterToBeanProxy.getContext(FilterToBeanProxy.java:177)
    at org.acegisecurity.util.FilterToBeanProxy.doInit(FilterToBeanProxy.java:119)
    at org.acegisecurity.util.FilterToBeanProxy.init(FilterToBeanProxy.java:189)
    at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:221)

    would anybody be able to give me some pointers please?
    Thanks in advance.
    Regards,
    -Eric

    Comment by Eric — March 15, 2007 @ 7:34 am

  49. Hi Martin,
    I have resolved the issue by changing the

    
    <constructor-arg value="/Login.jsp"/>
    to
    <constructor-arg value="/faces/Login.jsp"/>.
    There is a new problem that has come up i.e. when I changed the location of my Menu.jsp from /WebContent/Menu.jsp to /WebContent/common/Menu.jsp, I am unable to access the page: The requested resource (/common/Menu.jsp) is not available. Here is my objectDefinitionSource:

    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /secured/admin/**=ROLE_ADMINISTRATOR
    /common/users/**=ROLE_REQUESTER,ROLE_ADMINISTRATOR
    /**=ROLE_ANONYMOUS,ROLE_ADMINISTRATOR,ROLE_REQUESTER

    Comment by carp — March 15, 2007 @ 8:25 am

  50. Hi Eric,

    do you have the ConfigLoaderListener configured in your web.xml like the following?

    
    	<listener>
    		<listener-class>
    			org.springframework.web.context.ContextLoaderListener
    		</listener-class>
    	</listener>
    

    Cheers,
    Martin

    Comment by martin.grotzke — March 15, 2007 @ 10:48 am

  51. Hi Carp,

    in your previous post you did not have a <constructor-arg value="/Login.jsp"/>, so I do not really know what you changed…

    Do you have somewhere in your directory structure the path “/faces”?

    Concerning the “not available” issue of /common/Menu.jsp I’d suggest that you first make sure that this works without any authentication/authorization stuff.

    Can you turn on logging of related libs (e.g. acegi) and have a look at the logs, perhaps there’s some helpful output.

    Cheers,
    Martin

    Comment by martin.grotzke — March 15, 2007 @ 10:59 am

  52. Hi Martin,

    Since I am using MyFaces (as well as hibernate and spring), I have the following ContextListener:

    org.apache.myfaces.webapp.StartupServletContextListener

    And I don’t seem to be allowed to have 2 ContextListener registered. Thanks again for your help on this.
    -Eric

    Comment by Eric — March 15, 2007 @ 10:32 pm

  53. Hi Eric,

    why do you think that you’re not allowed to register more than 1 listener in your servlet container?
    What happens when you add the spring ContextLoaderListener?

    Cheers,
    Martin

    Comment by martin.grotzke — March 15, 2007 @ 10:59 pm

  54. Hi Martin,

    If I add the following to my web.xml file:

    <listener>
    <listener-class>
    org.springframework.web.context.ContextLoaderListener
    </listener-class>
    </listener>
    <listener>
    <listener-class>
    org.apache.myfaces.webapp.StartupServletContextListener
    </listener-class>
    </listener>

    I get the following exception:
    java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present -
    check whether you have multiple ContextLoader* definitions in your web.xml!
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:167)
    at org.springframework.web.context.ContextLoaderServlet.init(ContextLoaderServlet.java:83)
    at javax.servlet.GenericServlet.init(GenericServlet.java:212)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1139)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:966)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3956)

    Thank you,
    -Eric

    Comment by Eric — March 16, 2007 @ 3:14 am

  55. Hi Martin,

    I am sorry to pollute your awesome blog with this. I actually feel ashamed :-(. I removed the following from my web.xml and everything works.

    Thanks again for your help on this.
    -Eric

    <servlet>
    <servlet-name>SpringContextServlet</servlet-name>
    <servlet-class>
    org.springframework.web.context.ContextLoaderServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>

    Comment by Eric — March 16, 2007 @ 3:27 am

  56. No prob, Eric :)

    Comment by martin.grotzke — March 16, 2007 @ 12:03 pm

  57. Hi Martin,
    In your AuthenticationController you have two outcomes based on which u direct the user to either a login or failure page.
    I have different roles such as ADMINISTRATOR,PC MEMBER,REQUESTER,etc.
    What I wanted was that when an ADMINISTRATOR logs in he shhould be directed to an admin page but when a REQUESTER logs in he should get a different page and so on.
    I know one way that I can do this is by directing the user(irrespective of his role) to a common page and then use the tags but I dont want to add an extra page.
    Can you please help me with the issue.
    Thanks for all ur help in the past.

    Regards,
    Carp.

    Comment by carp — March 27, 2007 @ 7:49 am

  58. Hi Carp,

    the Authentication object that is returned from getAuthenticationManager().authenticate contains the list of permissions / roles (GrantedAuthorities). So you should be able to determine the role that the user has and return the appropriate outcome according to this.

    Cheers,
    Martin

    Comment by martin.grotzke — March 27, 2007 @ 9:38 am

  59. Hi Martin,
    I had tried extracting the role by: auth.getAuthorities()
    The output that I get for the above is: org.acegisecurity.GrantedAuthority;@1988886
    So how do I make the comparison and return the appropriate outcome.
    Also, I am trying to implement method security but facing some problems.
    Can u please tell me what changes do I need to make in applicationContext.
    Thanks.

    Regards,
    Carp.

    Comment by carp — March 28, 2007 @ 9:31 am

  60. getAuthorities returns an array, so you probably want to iterate over all authorities and see what’s the most appropriate (”highest”) one… You are doing this in the AuthenticationController, right?

    Cheers,
    Martin

    Comment by martin.grotzke — March 28, 2007 @ 9:46 am

  61. Hi Martin,
    I have got that working now.
    Please can you tell me how to secure method invocations.
    I have gone thru the reference guide and implemented
    the MethodSecuirtyInterceptor but that’s not enough. Please let me know what changes are required.
    Thanks a lot.

    Regards,
    Carp.

    Comment by carp — March 28, 2007 @ 12:15 pm

  62. I haven’t used security restrictions on methods until now, so I cannot tell you anything about that, sorry!

    Cheers,
    Martin

    Comment by martin.grotzke — March 28, 2007 @ 1:34 pm

  63. Hi Martin,
    Anways, u have been very kind for sparing ur time.
    Thanks a lot.

    Cheers :)
    Carp.

    Comment by carp — March 28, 2007 @ 4:09 pm

  64. the example is almost perfect.
    there is one context listener missing though:

    web.xml

    org.springframework.web.context.request.RequestContextListener

    Comment by Jakob — April 4, 2007 @ 1:19 pm

  65. Thanx, a lot people helped to improve it :)

    In my web.xml I do not have the RequestContextListener but the RequestContextFilter.

    In the API docs I just read that both seem to be alternatives…

    Cheers,
    Martin

    Comment by martin.grotzke — April 4, 2007 @ 2:14 pm

  66. Hi Martin,

    Thanks for your very informative blog. It looks like its gonna work v well for me if I can just fix a few issues. The first seems to be that the backing bean doesn’t get its authenticationManager value injected (its null when executing ‘authenticate’). My quite new to JSF et al so this is probably a config/version issue. Target is Tomcat 5.5 (via Eclipse).

    Any help appreciated.

    Regards
    Andy

    Here’s my applicationContext.xml

    
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
                           "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
    <beans>
     <bean id="authenticationController" class="com.asi.backing.AuthenticationController" scope="session">
      <property name="authenticationManager"><ref local="authenticationManager"/></property>
     </bean>
    
     <bean id="acegiFilterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
      <property name="filterInvocationDefinitionSource">
       <value>
        CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
        PATTERN_TYPE_APACHE_ANT
        /templates/css/**=#NONE#
        /**=httpSessionContextIntegrationFilter,securityRequestFilter,exceptionTranslationFilter,filterSecurityInterceptor
       </value>
      </property>
     </bean>
     <bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">
      <property name="context">
       <value>org.acegisecurity.context.SecurityContextImpl</value>
      </property>
     </bean>
     <bean id="securityRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter" />
     <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
      <property name="authenticationEntryPoint">
       <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
        <property name="loginFormUrl">
         <value>/login.jsf</value>
        </property>
        <property name="forceHttps"><value>false</value></property>
       </bean>
      </property>
      <property name="accessDeniedHandler">
       <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
        <property name="errorPage">
         <value>/accessDenied.jsf</value>
        </property>
       </bean>
      </property>
     </bean>
    
     <bean id="filterSecurityInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
      <property name="authenticationManager"><ref local="authenticationManager"/></property>
      <property name="accessDecisionManager">
       <!--
        The AffirmativeBased voter allows access if at least one voter votes
        to grant access. Use the UnanimousBased voter if you only want to
        grant access if no voter votes to deny access. -->
       <bean class="org.acegisecurity.vote.AffirmativeBased">
        <property name="decisionVoters">
         <list>
          <bean class="org.acegisecurity.vote.RoleVoter">
           <!--  Reset the role prefix to "", default is ROLE_ -->
           <property name="rolePrefix">
            <value>ROLE_</value>
           </property>
          </bean>
          <!--
           The authenticated voter grant access if e.g.
           IS_AUTHENTICATED_FULLY is an attribute -->
          <bean class="org.acegisecurity.vote.AuthenticatedVoter" />
         </list>
        </property>
       </bean>
      </property>
      <property name="objectDefinitionSource">
       <value>
        CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
        PATTERN_TYPE_APACHE_ANT
        /asi/**=IS_AUTHENTICATED_FULLY
       </value>
      </property>
     </bean> 
     <bean class="org.acegisecurity.providers.ProviderManager" id="authenticationManager">
      <property name="providers">
       <list>
        <ref local="daoAuthenticationProvider"/>
        <bean class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
         <property name="key" value="changeThis"/>
        </bean>
        <bean class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
         <property name="key" value="changeThis"/>
        </bean>
       </list>
      </property>
     </bean>
     <bean class="org.acegisecurity.providers.dao.DaoAuthenticationProvider" id="daoAuthenticationProvider">
      <property name="userDetailsService" ref="asiDaoImpl"/>
      <property name="userCache">
       <bean class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
        <property name="cache">
         <bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
          <property name="cacheManager">
           <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
          </property>
          <property name="cacheName" value="userCache"/>
         </bean>
        </property>
       </bean>
      </property>
     </bean>
     <bean class="com.asi.bo.Users" id="asiDaoImpl"/>
     <bean class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl" id="jdbcDaoImpl">
      <property name="dataSource">
       <ref bean="dataSource"/>
      </property>
     </bean>
     <bean class="org.springframework.jndi.JndiObjectFactoryBean" id="dataSource">
      <property name="jndiName" value="java:/comp/env/jdbc/ASi"/>
     </bean>
     <bean
      class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter" id="anonymousProcessingFilter">
      <property name="key" value="anonymous"/>
      <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
     </bean>
     <!-- This bean is optional; it isn't used by any other bean as it only listens and logs -->
     <bean class="org.acegisecurity.event.authentication.LoggerListener" id="loggerListener"/>
    </beans>
    
    

    Here’s my faces-config.xml

    
    
    <?xml version="1.0" encoding="UTF-8"?>
    <faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xi="http://www.w3.org/2001/XInclude"
     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-facesconfig_1_2.xsd">
     <managed-bean>
      <managed-bean-name>authenticationController</managed-bean-name>
      <managed-bean-class>com.asi.backing.AuthenticationController</managed-bean-class>
      <managed-bean-scope>session</managed-bean-scope>
      <managed-property>
       <property-name>username</property-name>
       <property-class>java.lang.String</property-class>
       <value>Fred</value>
      </managed-property>
      <managed-property>
       <property-name>password</property-name>
       <property-class>java.lang.String</property-class>
       <value/>
      </managed-property>
      <managed-property>
       <property-name>authenticationManager</property-name>
       <property-class>org.acegisecurity.AuthenticationManager</property-class>
       <value>#{authenticationManager}</value>
      </managed-property>
     </managed-bean>
     <navigation-rule>
      <from-view-id>/login.xhtml</from-view-id>
      <navigation-case>
       <from-action>#{authenticationController.authenticate}</from-action>
       <from-outcome>success</from-outcome>
       <to-view-id>/asi/main.jsf</to-view-id>
       <redirect/>
      </navigation-case>
      <navigation-case>
       <from-action>#{authenticationController.authenticate}</from-action>
       <from-outcome>failure</from-outcome>
       <to-view-id>/login.jsf</to-view-id>
      </navigation-case>
     </navigation-rule>
     <navigation-rule>
      <from-view-id>*</from-view-id>
      <navigation-case>
       <from-action>#{authenticationController.doLogout}</from-action>
       <to-view-id>/login.xhtml</to-view-id>
       <redirect/>
      </navigation-case>
     </navigation-rule>
     <application>
      <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
      <variable-resolver>org.springframework.web.jsf.DelegatingVariableResomµçfW#Â÷f&–&ĆR×&W6öÇfW#ŕТÂöĆ–6F–öăŕĐŁÂöf6W2Ö6öćf–sŕĐ Đ

    And my web.xml

    
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
     <display-name>ASi</display-name>
     <context-param>
      <param-name>org.ajax4jsf.SKIN</param-name>
      <param-value>blueSky</param-value>
     </context-param>
     <context-param>
      <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
      <param-value>.xhtml</param-value>
     </context-param>
     <context-param>
      <param-name>facelets.REFRESH_PERIOD</param-name>
      <param-value>2</param-value>
     </context-param>
     <context-param>
      <param-name>facelets.DEVELOPMENT</param-name>
      <param-value>true</param-value>
     </context-param>
     <context-param>
      <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
      <param-value>server</param-value>
     </context-param>
     <context-param>
      <param-name>com.sun.faces.validateXml</param-name>
      <param-value>true</param-value>
     </context-param>
     <context-param>
      <param-name>com.sun.faces.verifyObjects</param-name>
      <param-value>true</param-value>
     </context-param>
     <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/applicationContext.xml</param-value>
     </context-param>
     <context-param>
      <param-name>com.exadel.vcp.trialKey</param-name>
      <param-value>trial_key_goes_here</param-value>
     </context-param>
     <filter>
      <filter-name>securityFilter</filter-name>
      <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
      <init-param>
       <param-name>targetClass</param-name>
       <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
      </init-param>
     </filter>
     <filter>
      <display-name>Ajax4jsf Filter</display-name>
      <filter-name>ajax4jsf</filter-name>
      <filter-class>org.ajax4jsf.Filter</filter-class>
     </filter>
     <filter>
      <filter-name>RequestContextFilter</filter-name>
      <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
     </filter>
     <filter-mapping>
      <filter-name>securityFilter</filter-name>
      <servlet-name>Faces Servlet</servlet-name>
      <dispatcher>FORWARD</dispatcher>
      <dispatcher>REQUEST</dispatcher>
     </filter-mapping>
     <filter-mapping>
      <filter-name>ajax4jsf</filter-name>
      <servlet-name>Faces Servlet</servlet-name>
      <dispatcher>REQUEST</dispatcher>
      <dispatcher>FORWARD</dispatcher>
      <dispatcher>INCLUDE</dispatcher>
     </filter-mapping>
     <filter-mapping>
      <filter-name>RequestContextFilter</filter-name>
      <servlet-name>Faces Servlet</servlet-name>
     </filter-mapping>
     <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
     </listener>
     <!--
     /*********************************************************************
       Servlets
     *********************************************************************/
     -->
     <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>*.jsf</url-pattern>
     </servlet-mapping>
     <login-config>
      <auth-method>BASIC</auth-method>
     </login-config>
     <resource-ref>
      <res-ref-name>jdbc/ASi</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
      <res-sharing-scope>Shareable</res-sharing-scope>
     </resource-ref>
    </web-app>
    
    

    Comment by Andy — April 26, 2007 @ 1:03 pm

  67. I tried to run the application. But my jsf file could not resolve the values which are coming from spring session scope bean. It is giving me error “Scope ’session’ is not active; nested exception is java.lang.IllegalStateException: thread-bound request: use RequestContextFilter”.

    I had the same problem like usesr “Umesh Sinha”
    My solution is to add the RequestContextListener

    org.springframework.web.context.request.RequestContextListener

    Hope this helps

    Comment by NewToAcegi — August 16, 2007 @ 3:21 pm

  68. Hi Martin! Thanks for the blog! Is a very important information. Well, in my application, when i insert the ACEGI filters in my web.xml, the application not start up throwing the folowing erro:

    SEVERE: Error filterStart

    What would be?

    Here’s may web.xml:

    contextConfigLocation
    classpath:/applicationContext.xml

    org.springframework.web.context.ContextLoaderListener

    org.springframework.web.context.request.RequestContextListener

    Faces Servlet
    javax.faces.webapp.FacesServlet
    1

    Faces Servlet
    /faces/*

    30

    faces/Login.jsp

    com.sun.faces.verifyObjects
    false

    com.sun.faces.validateXml
    true

    javax.faces.STATE_SAVING_METHOD
    client


    Acegi Filter Chain Proxy
    org.acegisecurity.util.FilterToBeanProxy

    targetBean
    acegiFilterChainProxy

    Acegi Filter Chain Proxy
    Faces Servlet
    FORWARD
    REQUEST

    Comment by Paulo Melo — October 2, 2007 @ 7:38 pm

  69. Hi,

    it’s good to see that it’s still useful :)

    If there’s no more information in catalina.out, can you check other log files (like localhost*.log)?
    These should contain more details about the error then.

    Cheers,
    Martin

    Comment by martin.grotzke — October 2, 2007 @ 8:17 pm

  70. Hi Martin, thank you for response. Already running but the ACEGI filters do not filter.(!) Like this: http://forum.springframework.org/showthread.php?p=144734#post144734

    Do you know what is this?

    Again, thanx!

    A Paz!

    Comment by Paulo — October 4, 2007 @ 9:26 pm

  71. Nope, I’m sorry, I haven’t experienced such behavior.

    Hopefully you’ll find the reason for this,
    cheers,
    Martin

    Comment by martin.grotzke — October 5, 2007 @ 9:38 am

  72. I tried with the rememberMe code provided above, but I am not getting it.
    Where to send the check box value??
    Where should I write the code related to it.

    Please suggest me to implement it.
    Thank you in advance

    Comment by Sridevi — October 7, 2007 @ 1:17 pm

  73. I haven’t included the rememberMe functionality, so I can’t tell you how to name the checkbox.
    But you might have a look at the RememberMeServices and check which request parameter is tested therein.

    Cheers,
    Martin

    Comment by martin.grotzke — October 7, 2007 @ 5:51 pm

  74. Hi,
    I had followed this blog to integrate jsf with acegi.
    But i could not make refer the AuthenticationManager from my backing bean .Though i had configured my applicationContext.xml, it was not picking the authentication information.Pls help me

    regards,
    Lakshmi.

    Comment by mlakshmi — January 3, 2008 @ 2:20 pm

  75. Hi Lakshmi,

    what do you mean with could not make refer the AuthenticationManager from my backing bean?
    Can you clarify your problem a little bit more, please? What exactly does not work?

    Cheers,
    Martin

    Comment by martin.grotzke — January 4, 2008 @ 6:31 pm

  76. Hi,

    I try your code and get error by:
    /*
    * perform authentication
    */
    final Authentication auth = getAuthenticationManager().authenticate(authReq);

    I have to cast it to:
    final Authentication auth = ((AuthenticationManager) getAuthenticationManager()).authenticate(authReq);

    Comment by Thomas Roland — January 30, 2008 @ 1:18 pm

  77. Hi,

    Hwere can I find the deployable example?

    Comment by Thomas Roland — February 10, 2008 @ 9:55 am

  78. Hi Martin,

    Now I can get your example run. But I have a question/problem:

    The “objectDefinitionSource” by me looks as follow:

    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    PATTERN_TYPE_APACHE_ANT
    /pages/admin/**=ROLE_ADMIN,ROLE_SUPERVISOR
    /pages/supervisor/**=ROLE_SUPERVISOR
    /pages/user/**=ROLE_USER
    /pages/**=IS_AUTHENTICATED_FULLY

    After I loggined as a role of Admin and when I access the page “http://localhost:8585/TestMyAcegiFacelets/pages/admin/admin.faces”, I got access denied error.

    Could you explain a little bit about using and configuring the “objectDefinitionSource”

    Regards

    Thomas

    Comment by thomas — February 12, 2008 @ 10:14 am

  79. Hi Thomas,

    concerning the objectDefinitionSource I suspect that acegi docs explain this in a better way than I could ;)

    Regarding your issue: do have configured your voters correctly (AffirmativeBased)?

    Cheers,
    Martin

    Comment by martin.grotzke — February 12, 2008 @ 10:33 am

  80. Hi Martin,

    Nice to get your answer finally. :-)

    Yuo are right. I check my code again and correct it to using “AffirmativeBased”. It is better. :-)

    But another question:
    After I logined, the page “welcome.xhtml” is shown. In this page there are some links as follow:

    This means, if I logged as User and when I click the link to “toAdmin”, I should get access denied. The “toAdmin” links to “Admin.xhtml” as follow:

    But it’s not the case. I click the “toAdmin” and it links to “Admin.xhtml”. Only when I click the “toSupervisor” in “Admin.xhtml”, I get the access denied.

    Besides, when I access the page “http://localhost:8585/TestMyAcegiFacelets/pages/admin/admin.faces” the first time, I get no access denied. By the second time I get access denied.

    It seems it’s a step later. I’ve heard this is the problem of using JSF because JSF has, by design, a “navigation engine” that relies on forwards instead of redirect. The displayed URL in the browser rarely corresponds to the actual displayed page. (in fact, the URL address is the previous navigation).

    Don’t have such a problem? How can one solve such a problem?

    Regards

    Thomas

    Comment by thomas — February 12, 2008 @ 12:02 pm

  81. I wonder why my program code can not be shown?

    Here again:
    welcome.xhtml
    **************

    Admin.xhtml
    ***********

    Comment by thomas — February 12, 2008 @ 12:05 pm

  82. I wonder I can’t upload jsf code?

    Comment by thomas — February 12, 2008 @ 12:07 pm

  83. Try

    <pre>

    followed by a

    <code>

    tag around your code.

    Comment by martin.grotzke — February 12, 2008 @ 2:11 pm

  84. Thomas,

    you might try to add a

    <dispatcher>FORWARD</dispatcher>

    element to your acegi filter mapping, so that this is applied to any forward targets matching the specified servlet or URL pattern.

    Cheers,
    Martin

    Comment by martin.grotzke — February 12, 2008 @ 2:42 pm

  85. My filter-mapping looks as follow. Isn’t correct?

    
    	<filter-mapping>
    		<filter-name>Acegi Filter Chain Proxy</filter-name>
    		<url-pattern>/*</url-pattern>
    		<dispatcher>FORWARD</dispatcher>
    		<dispatcher>REQUEST</dispatcher>
    	</filter-mapping>
    

    Comment by thomas — February 12, 2008 @ 4:12 pm

  86. Here again my codes:

    welcome.xhtml:

    
    <h:form>
    	<h:panelGrid border="1" columns="1">
    		<h:commandLink action="toUser">
    			<h:outputText value="To User"></h:outputText>
    		</h:commandLink>
    		<h:commandLink action="toAdmin">
    			<h:outputText value="To Admin"></h:outputText>
    		</h:commandLink>
    		<h:commandLink action="toSupervisor">
    			<h:outputText value="To Supervisor"></h:outputText>
    		</h:commandLink>
    	</h:panelGrid>
    </h:form>
    ...
    

    Admni.xhtml

    
    <h:form>
    	<h:commandLink action="toSupervisor">
    		<h:outputText value="To Supervisor"></h:outputText>
    	</h:commandLink>
    </h:form>
    ...
    

    Comment by thomas — February 12, 2008 @ 4:15 pm

  87. Ok. What about setting a

    <redirect/>

    in the faces-config for these navigation cases?

    Comment by martin.grotzke — February 12, 2008 @ 5:30 pm

  88. This helps.

    Now I see what’s the reason why you use this in your faces-config.

    Many thanks!

    Comment by thomas — February 13, 2008 @ 9:37 am

  89. You’re welcome :)

    Comment by martin.grotzke — February 13, 2008 @ 10:21 am

  90. Hi,

    I am implementing Acegi in my JSF application. Both authentication and authorization is working fine with my application. But If i register a new user in my application then i have to stop and restart the server inorder to authenticate that new user. Else it shows “user not found” message . Acegi retrieves all the authentication information from database while loading the application itself. It was not holding the newly registered user’s details. i searched in the net and tried to instantiate the Acegi’s application context from its xml files explicitly when a new user is activated. But it was not working. How can we add a new user to Authentication object??

    Comment by lakshmi — March 11, 2008 @ 11:30 am

  91. Hi Laskhmi,

    have you implemented acegi authentication as described here?

    So that I understand your problem: your authentication provider does not provide authentication information correctly?

    <quote>Acegi retrieves all the authentication information from database while loading the application itself.</quote>

    Why does it do this? What are the differences compared to the “standard” acegi configuration?

    Cheers,
    Martin

    Comment by martin.grotzke — March 11, 2008 @ 12:33 pm

RSS feed for comments on this post. TrackBack URI

Leave a comment

*
To prove you're a person (not a spam script), type the security word shown in the picture.
Anti-Spam Image

Powered by WordPress