acegi-security and icefaces
[Logo]
Forums for ICEfaces and ICEpdf
[Search] Search   [Recent Topics] Recent Topics   [Groups] Home Page | www.icefaces.org  [Register] Register  [Login] Login 
acegi-security and icefaces  XML
Forum Index -> General Help Go to Page: Previous  1, 2, 3 Next 
Author Message
jtp51


Joined: 12/07/2006 00:00:00
Messages: 139
Offline


Confirmed:

"The login form; it has input fields for the username and password, j_username and j_password, respectively, and a form action pointing to j_acegi_security_check since that is what the authenticationProcessingFilter filter listens for to capture every login form submission."

So, how do I solve this?

Thanks,

--Todd

--Todd
Christian Teichert

Joined: 04/07/2006 00:00:00
Messages: 14
Offline


In my app it works as easily as you describe it:

<form action="j_acegi_security_check" method="POST" >
<input type="text" name="j_username" value="" />
<input type="password" name="j_password" />
<input name="Login" value="Login" type="submit" />
</form>

--
p.s.: better use a normal html form for the login page, as ICEfaces will add it's something of it's own to the controls ' ids.


Message was edited by: Christian Teichert
jtp51


Joined: 12/07/2006 00:00:00
Messages: 139
Offline


Christian: thank you for following up. I am about at that point, but would like to try one other approach.

I hate to give up the JSF validation on the two fields...

Thanks,

--Todd

--Todd
Sixty4

Joined: 22/06/2006 00:00:00
Messages: 29
Offline


Dear Christian, dear Todd,

it's nice to see you working so hard to solve these problems ... while still being on holiday. ;-)

Good luck!
Thomas
jtp51


Joined: 12/07/2006 00:00:00
Messages: 139
Offline


David: My other approach did not work. I tried to use the MyFaces Tomahawk example - but of course that was wrong and doesn't work.

What MyFaces has in their Wiki for a acegi-security solution is wrong. I confirmed this on the Springframework forums.

Therefore, I will give up the nice JSF components for the login screen and use a .jsp page.

I tried the bean approach, but the information is so uncomplete, it's a waste of time.

If your interested, I've attached my login.jspx with the Tomahawk references.

Acegi-security does not work with the Controller model of JSF.

This is not an ICEfaces issue, just a JSF issue.

Thanks,

--Todd
 Filename login.jspx [Disk] Download
 Description No description given
 Filesize 3 Kbytes
 Downloaded:  381 time(s)


--Todd
aberrant80

Joined: 20/07/2006 00:00:00
Messages: 34
Offline


I'm interested in finding out if you managed to get your "other approach" to work.
dclounch

Joined: 27/03/2007 00:00:00
Messages: 5
Offline


jtp51 wrote:
David: My other approach did not work. I tried to use the MyFaces Tomahawk example - but of course that was wrong and doesn't work.

What MyFaces has in their Wiki for a acegi-security solution is wrong. I confirmed this on the Springframework forums.

Therefore, I will give up the nice JSF components for the login screen and use a .jsp page.

I tried the bean approach, but the information is so uncomplete, it's a waste of time.

If your interested, I've attached my login.jspx with the Tomahawk references.

Acegi-security does not work with the Controller model of JSF.

This is not an ICEfaces issue, just a JSF issue.

Thanks,

--Todd 


About a year later I am wondering if things are better? I was looking at Phil's forwarding of variables via the loginProxyBean class. Does that help?
Or should I just give up now? I can see the j_username and j_password being set in the map, but is that enough? I am still not getting authenticated with good credentials.

I am new to icefaces and I am concerned about how to get renderedOnUserRole set up properly with authentication and authorization. If Acegi is hopeless then is there another framework that works with JSF/ice?

brad.kroeger

Joined: 26/10/2004 00:00:00
Messages: 263
Offline


Here is an example of a working implementation in an ICEfaces application. An AuthenticationController bean helps to perform the authenticationProcessingFilter and logoutFilter functions as per
http://www.javakaffee.de/blog/2006/07/04/jsfacegi-authentication-with-a-backing-bean/? .

First of all the jars, I'm using jars from spring-framework 2.0.3:

acegi-security-1.0.3.jar
aopalliance.jar
aspectjrt.jar
commons-attributes-api.jar
commons-codec.jar
commons-lang.jar
ehcache-1.2.4.jar
jakarta-oro-2.0.8.jar
jstl.jar
spring.jar
spring-aspects.jar
standard.jar

Add the following to your web.xml:
Code:
 	<!-- Security -->
 	
 	<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>Persistent Faces Servlet</servlet-name>
 	</filter-mapping>
 	
 	<listener>
 	    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 	  </listener>
 	
 	<filter>
         <filter-name>Acegi Filter Chain Proxy</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-mapping>
       <filter-name>Acegi Filter Chain Proxy</filter-name>
       <servlet-name>Persistent Faces Servlet</servlet-name>
       <dispatcher>FORWARD</dispatcher>
       <dispatcher>REQUEST</dispatcher>
     </filter-mapping>
 

Add the following to your faces.config:
Code:
 <!-- Security Start -->	
 	<application>
         <variable-resolver>
             org.springframework.web.jsf.DelegatingVariableResolver
         </variable-resolver>		
 	</application>
 
 	<lifecycle>
 		<phase-listener>com.icesoft.icefaces.site.acegi.NoCachePhaseListener</phase-listener>
 	</lifecycle>
 <!-- Security Finish -->
 

Here is the applicationContext.xml. In our application we are doing our own implementation of userDetailsService (OurUserDetailsService) it's up to you how you want to implement this, please see the acegi documentation for your options:
Code:
 <?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="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
 		<property name="filterInvocationDefinitionSource">
 			<value>
 				CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
 				PATTERN_TYPE_APACHE_ANT
 				/**=httpSessionContextIntegrationFilter,securityContextHolderAwareRequestFilter,exceptionTranslationFilter,filterInvocationInterceptor
 			</value>
 		</property>
 	</bean>
 
 	<bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>
    
 	<bean id="securityContextHolderAwareRequestFilter" 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="/index.jsp"/>
 				<property name="forceHttps" value="false"/>
 			</bean>
 		</property>
 		<property name="accessDeniedHandler">
 			<bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
 			<property name="errorPage" value="/index.jsp"/>
 			</bean>
 		</property>
 	</bean>
 
 	<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
 		<property name="authenticationManager" >
 			<ref bean="authenticationManager"/>
 		</property>
 		<property name="accessDecisionManager">
 			<bean class="org.acegisecurity.vote.AffirmativeBased">
 				<property name="allowIfAllAbstainDecisions" value="false"/>
 				<property name="decisionVoters">
 					<list>
 						<bean class="org.acegisecurity.vote.RoleVoter"/>
 						<bean class="org.acegisecurity.vote.AuthenticatedVoter"/>
 					</list>
 				</property>
 			</bean>
 		</property>
 		<property name="objectDefinitionSource">
 			<value>
 				CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
 				PATTERN_TYPE_APACHE_ANT
 				/secure/**=ROLE_Administration
 				/general/**=IS_AUTHENTICATED_REMEMBERED
 			</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" ref="userDetailsService"/>
 		<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>
 
 	<!-- UserDetailsService is the most commonly frequently Acegi Security interface implemented by end users -->
 	<bean id="userDetailsService" class="com.icesoft.icefaces.site.acegi.OurUserDetailsService">
 
 	</bean>
 
     <bean id="authenticationController" class="com.icesoft.icefaces.site.acegi.AuthenticationController" scope="session">
         <property name="authenticationManager"><ref bean="authenticationManager"/></property>
     </bean>
 	
 	<!-- This bean is optional; it isn't used by any other bean as it only listens and logs -->
 	<bean id="loggerListener" class="org.acegisecurity.event.authentication.LoggerListener"/>
 
 </beans>
 

Here are the classes you need to add to your application:
Code:
 public class NoCachePhaseListener implements PhaseListener {
 
 	   public PhaseId getPhaseId() {
 	       return PhaseId.RENDER_RESPONSE;
 	   }
 
 	   public void afterPhase(PhaseEvent phaseEvent) {
 	   }
 
 	   public void beforePhase(PhaseEvent phaseEvent) {
 	       FacesContext facesContext = phaseEvent.getFacesContext();
 	       HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
 	       response.addHeader("Pragma", "no-cache");
 	       response.addHeader("Cache-Control", "no-cache");
 	       response.addHeader("Cache-Control", "no-store");
 	       response.addHeader("Cache-Control", "must-revalidate");
 	       response.addHeader("Expires", "Mon, 1 Jan 2006 05:00:00 GMT");//in the past
 	   }
 	} 
 

Code:
 public final class AuthenticationController {
 
      private static final Log LOG = LogFactory.getLog( AuthenticationController.class );
 
      // injected properties
      private AuthenticationManager _authenticationManager;
 
      public String authenticate(String userName, String password) throws AuthenticationException{
          
          String outcome = "failure";
          
          final HttpServletRequest request = getRequest();
 
          try {
              final UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(
                      userName, password );
 
              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";
          }
          return outcome;
      }
 
      private HttpServletRequest getRequest() {
          return (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
      }
 
      public AuthenticationManager getAuthenticationManager() {
          return _authenticationManager;
      }
 
      public void setAuthenticationManager(
              AuthenticationManager authenticationManager ) {
          _authenticationManager = authenticationManager;
      }
 
 }
 

In your bean that is performing the login, you can now add the following code. We are returning a String here because the method is bound to a action attribute on a commandButton. "loginMessage" is a String used to display errors in our UI:
Code:
             // begin acegi login
             persistentFacesState = PersistentFacesState.getInstance();
             authenticationController = ((AuthenticationController)persistentFacesState.getFacesContext().getApplication().getVariableResolver().resolveVariable(persistentFacesState.getFacesContext(), "authenticationController"));
             try{
                authenticationController.authenticate(username,password);
             } catch (AuthenticationException e) {
                 loginMessage = e.getMessage() + ".";
                 return "failed";
             }
             // end acegi login
 

Here is the logout code:
Code:
         // acegi logout
         SecurityContextHolder.clearContext();
         final HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
         final HttpSession session = request.getSession();
         session.removeAttribute( HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY );
         session.invalidate();
 


In our case, we are using our implementation of userDetailsService to construct an acegi User object with roles from an existing database. The existing database has group names that we concatenate to ROLE_ in order to construct an array of GrantedAuthorities.

We can now use ROLE_administration to access the /secure portions of our site or in our renderedOnUserRole/enabledOnUserRole attributes of ICEfaces components.

Brad Kroeger
Developer
ICEsoft Technologies, Inc.
[Email]
brad.kroeger

Joined: 26/10/2004 00:00:00
Messages: 263
Offline


userDetails implementation is covered in this post:

http://www.icefaces.org/JForum/posts/list/3390.page

Brad Kroeger
Developer
ICEsoft Technologies, Inc.
[Email]
philip.breau


Joined: 08/05/2006 00:00:00
Messages: 2628
Offline


I've attached the built example if anyone's interested. This is built from the current 1.6 trunk.

Philip
 Filename security.war [Disk] Download
 Description Security Example war
 Filesize 8382 Kbytes
 Downloaded:  434 time(s)


.
eashwaranp

Joined: 12/02/2007 00:00:00
Messages: 135
Offline


Brad & Philip,

The AuthenticationController and OurUserDetailsService way of implementing ACEGI security simply ROCKS!

After some research I got this working with my ICEfaces application. I'm also able to use isUserInRole method inside a backing bean.

Thanks for explaining these in so much detail.

Regards,
Eashwaran.
craig

Joined: 28/11/2006 00:00:00
Messages: 162
Offline


Hi how did you get this working from within a backing bean?

Durring normal requests i use
Code:
 Authentication auth = SecurityContextHolder.getContext().getAuthentication();
 


to get my principle. However, durring server push or new Threads this doesnt work, is there a way around this?

Thanks

Craig
eashwaranp

Joined: 12/02/2007 00:00:00
Messages: 135
Offline


I don't use the SecurityContextHolder, instead I use the HttpServletRequest's isUserInRole or getUserPrincipal. The request can be obtained from the FacesContext's external context (which is available only at request time, and not from any session context or thread that is not in request scope).

I believe the ACEGI security uses ThreadLocal to store the security context, but I'm not very clear how one would use this to obtain the principal. Reading the ACEGI docs, it does appear that your method of using SecurityContextHolder is correct and it should work.

Excerpt code from http://www.acegisecurity.org/docbook/acegi.html
Code:
 Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
 
 if (obj instanceof UserDetails) {
   String username = ((UserDetails)obj).getUsername();
 } else {
   String username = obj.toString();
 }


So, I'm not sure why this won't work. Maybe the ICEfaces gurus can help us here.
Regards,
Eashwaran.
dinobhai

Joined: 29/11/2006 00:00:00
Messages: 117
Offline


hi

we have been thinking of using a security API for our application but we are not using springs framework would we still be able to use acegi or is there any other alternative ..

Rajat
rainwebs


Joined: 24/07/2007 00:00:00
Messages: 237
Offline


Well, you can't use Acegi without the Spring Framework. So, if you can't use Spring you have to skip Acegi. In this case you may fall back to the JEE standards the application server delivers (JAAS). But, this isn't as portable as using Acegi.

ICEfaces book . ICEcube . ICEfusion . ICEfaces Technical Blog Award
 
Forum Index -> General Help Go to Page: Previous  1, 2, 3 Next 
Go to:   
Powered by JForum 2.1.7ice © JForum Team