Announcement Announcement Module
Collapse
No announcement yet.
Acegi in portlets Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Acegi in portlets

    Hi All:

    Hope this isn't too far off topic. I am wondering if anyone has experience using the LifeRay portlet container (www.liferay.com). In its newest version. the business tier is built using Spring (and optionally EJB) . but JAAS is used for authentication. I would like to use Acegi ACL-based authorization within a portlet. I am assuming that once the principals are placed in the session on login, that I can simply retrieve them and use Acegi authorization within the context of the individual portlet. Does this seem like a tenable approach?

    Any feedback much appreciated.

    Thanks!

    Dave

  • #2
    Try using the container adapters included with Acegi Security, which will integrate with your container authentication system and ensure the Principal made available to web applications is actually Acegi Security's Authentication. This can thus be used with Acegi Securty's ACL package.

    Comment


    • #3
      Thanks, Ben. I'll give it a try .

      Comment


      • #4
        recommened approach for impl independent security in portals

        What the recommened approach for implementation independent security in portals.. In Sun One Portal there is a proprietary class called SSOTokenManager. How does that fit into Acegi?

        Comment


        • #5
          Filters Don't Work w/ Portlets

          One of the biggest problem with using Acegi with Portlets is that the Filters in the portlet's wepapp don't run. Since there is no servlet request, there is nothing to filter.

          I've built a custom PortalAuthenticationProvider, SecurityEnforcementInterceptor, and SessionIntegrationInterceptor for use with Spring Portlet MVC and with Acegi security. They are working very well for us at this point. What I have doesn't support ObjectDefinitionSource or AbstractSecurityInterceptor, so there is no support for Voters, but it does support Also it is currently based on 0.6.1, so it is a bit dated -- I am planning to update to 0.8.2 later this month.

          If you are interested in seeing these, I'll be happy to send them to you. Send me an email: jlewis at arcanumintl dot com.

          Ben, if you are interested in working on more mainstream support of portlets within Acegi, I would be really happy to help. I am one of the main people working on the Spring Portlet MVC framework and I've had a number of people ask about Acegi already.

          Comment


          • #6
            Perhaps...

            Perhaps... security belongs at the level of portal I have since realized... What might be more benefitial is to integrate acegi with jetspeed2 for instance..

            Comment


            • #7
              Portal Security

              The problem we found is that the security framework offered by most portals was too coarse for our needs. We needed something very fine-grained, like we have with Acegi.

              We still use the portal for authentication, but we handle role-level authorization within our own app via Acegi.

              Comment


              • #8
                Can you give an example?

                Can you give an example? Where it is too course grained?

                Comment


                • #9
                  Security Granularity

                  In our commercial application, we need to manage access down to the object and even field level and manage what kind of access the user has to that object/field (i.e. create, read, update, delete). There are hundreds of these permissions. We then allow the organization to aggregate a set of these permissions into a user role and then assign multiple roles to a given user. None of the portals we looked at could manage this kind of detail.

                  To further complicate things, we have some servlet-based content that is integrated into our portlet application (such as images) that also need to be security controller. By using Acegi, we can use the portal authentication to check authorization on the servlet side as well.

                  Comment


                  • #10
                    Sounds like an interesting implementation. Is it something you could share with the community, or is it internal?

                    Comment


                    • #11
                      Absolutely -- Here are the classes I created for our initial integration of Acegi into the Spring Portlet MVC framework.

                      The first is simply a class to represent a user who is already logged into the portal -- it gets the user name and other info out of the portlet request:

                      Code:
                      package com.arcanumintl.portlet.acegi;
                      
                      import java.io.Serializable;
                      import java.util.HashMap;
                      import java.util.Map;
                      
                      import javax.portlet.PortletRequest;
                      
                      public class PortalUser implements Serializable {
                      
                      	private static final long serialVersionUID = 2L;
                      	
                      	private Map userInfo;
                      	
                      	private static final String USER_NAME         = "user.name";
                      	private static final String USER_NAME_FULL    = "user.name.full";
                      	private static final String USER_EMAIL        = "user.email";
                      	private static final String USER_ORGANIZATION = "user.organization";
                      	private static final String USER_TIMEZONE     = "user.timezone";
                      	private static final String USER_LOCALE       = "user.locale";
                      	
                      	public PortalUser(PortletRequest request) {
                      		super();
                      		this.userInfo = (Map)request.getAttribute(PortletRequest.USER_INFO);
                      		if (this.userInfo == null) this.userInfo = new HashMap();
                      	}
                      	
                      	public String getUserName() {
                      		return (String)userInfo.get(USER_NAME);
                      	}
                      	public String getUserNameFull() {
                      		return (String)userInfo.get(USER_NAME_FULL);
                      	}
                      	public String getUserEmail() {
                      		return (String)userInfo.get(USER_EMAIL);
                      	}
                      	public String getUserOrganization() {
                      		return (String)userInfo.get(USER_ORGANIZATION);
                      	}
                      	public String getUserTimezone() {
                      		return (String)userInfo.get(USER_TIMEZONE);
                      	}
                      	public String getUserLocale() {
                      		return (String)userInfo.get(USER_LOCALE);
                      	}
                      
                      	public String toString() {
                      		return getUserName();
                      	}
                      }
                      Here is the AuthenticationProvider that automatically trusts the credentials if they came from a portal:

                      Code:
                      package com.arcanumintl.portlet.acegi;
                      
                      import net.sf.acegisecurity.Authentication;
                      import net.sf.acegisecurity.UserDetails;
                      import net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider;
                      
                      public class PortalAuthenticationProvider extends DaoAuthenticationProvider {
                      
                      	
                      	/* (non-Javadoc)
                      	 * @see net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider#isPasswordCorrect(net.sf.acegisecurity.Authentication, net.sf.acegisecurity.UserDetails)
                      	 */
                      	protected boolean isPasswordCorrect(Authentication authentication, UserDetails user) {
                      		if (authentication.getCredentials() instanceof PortalUser) {
                      			PortalUser portalUser = (PortalUser)authentication.getCredentials();
                      			return (user.getUsername().equals(portalUser.getUserName()));
                      		}
                      		return super.isPasswordCorrect(authentication, user);
                      	}
                      
                      }
                      Here is the Portlet version of the SessionContextIntegrationInterceptor:

                      Code:
                      package com.arcanumintl.portlet.acegi;
                      
                      import javax.portlet.PortletException;
                      import javax.portlet.PortletRequest;
                      import javax.portlet.PortletResponse;
                      import javax.portlet.PortletSession;
                      import javax.portlet.RenderRequest;
                      import javax.portlet.RenderResponse;
                      
                      import org.apache.commons.logging.Log;
                      import org.apache.commons.logging.LogFactory;
                      import org.springframework.beans.factory.InitializingBean;
                      import org.springframework.web.portlet.HandlerInterceptor;
                      import org.springframework.web.servlet.ModelAndView;
                      
                      import net.sf.acegisecurity.context.Context;
                      import net.sf.acegisecurity.context.ContextHolder;
                      import net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter;
                      
                      public class PortletSessionContextIntegrationInterceptor
                      		implements InitializingBean, HandlerInterceptor {
                      
                          //~ Static fields/initializers =============================================
                      
                          protected static final Log logger = LogFactory.getLog(PortletSessionContextIntegrationInterceptor.class);
                          public static final String ACEGI_SECURITY_CONTEXT_KEY = HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY;
                      	private static final String SESSION_EXISTED = PortletSessionContextIntegrationInterceptor.class.getName() + ".SESSION_EXISTED";
                      
                          //~ Instance fields ========================================================
                      
                      	private Class context;
                      	private Object contextObject;
                      
                          /**
                           * Indicates if this interceptor can create a <code>PortletSession</code> if needed
                           * &#40;sessions are always created sparingly, but setting this value to false
                           * will prohibit sessions from ever being created&#41;. Defaults to true.
                           */
                          private boolean allowSessionCreation = true;
                      
                          //~ Methods ================================================================
                      
                          public void setAllowSessionCreation&#40;boolean allowSessionCreation&#41; &#123;
                              this.allowSessionCreation = allowSessionCreation;
                          &#125;
                      
                          public boolean isAllowSessionCreation&#40;&#41; &#123;
                              return allowSessionCreation;
                          &#125;
                      
                          public void setContext&#40;Class secureContext&#41; &#123;
                              this.context = secureContext;
                          &#125;
                      
                          public Class getContext&#40;&#41; &#123;
                              return context;
                          &#125;
                      
                          public void afterPropertiesSet&#40;&#41; throws Exception &#123;
                              if &#40;&#40;this.context == null&#41;
                                  || &#40;!Context.class.isAssignableFrom&#40;this.context&#41;&#41;&#41; &#123;
                                  throw new IllegalArgumentException&#40;
                                      "context must be defined and implement Context &#40;typically use net.sf.acegisecurity.context.security.SecureContextImpl&#41;"&#41;;
                              &#125;
                      
                              this.contextObject = generateNewContext&#40;&#41;;
                          &#125;
                      
                          
                      	/* &#40;non-Javadoc&#41;
                      	 * @see org.springframework.web.portlet.HandlerInterceptor#preHandle&#40;javax.portlet.PortletRequest, javax.portlet.PortletResponse, java.lang.Object&#41;
                      	 */
                      	public boolean preHandle&#40;PortletRequest request, PortletResponse response,
                      			Object handler&#41; throws Exception &#123;
                      
                              if &#40;ContextHolder.getContext&#40;&#41; != null&#41; &#123;
                                  if &#40;logger.isWarnEnabled&#40;&#41;&#41; &#123;
                                      logger.warn&#40;
                                          "ContextHolder should have been null but contained&#58; '"
                                          + ContextHolder.getContext&#40;&#41; + "'; setting to null now"&#41;;
                                  &#125;
                      
                                  ContextHolder.setContext&#40;null&#41;;
                              &#125;
                      
                              PortletSession portletSession = null;
                              boolean portletSessionExistedAtStartOfRequest = false;
                      
                              try &#123;
                                  portletSession = request.getPortletSession&#40;false&#41;;
                              &#125; catch &#40;IllegalStateException ignored&#41; &#123;&#125;
                      
                              if &#40;portletSession != null&#41; &#123;
                                  portletSessionExistedAtStartOfRequest = true;
                      
                                  Object contextObject = portletSession.getAttribute&#40;ACEGI_SECURITY_CONTEXT_KEY, PortletSession.APPLICATION_SCOPE&#41;;
                      
                                  if &#40;contextObject != null&#41; &#123;
                                      if &#40;contextObject instanceof Context&#41; &#123;
                                          if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
                                              logger.debug&#40;
                                                  "Obtained from ACEGI_SECURITY_CONTEXT a valid Context and set to ContextHolder&#58; '"
                                                  + contextObject + "'"&#41;;
                                          &#125;
                      
                                          ContextHolder.setContext&#40;&#40;Context&#41; contextObject&#41;;
                                      &#125; else &#123;
                                          if &#40;logger.isWarnEnabled&#40;&#41;&#41; &#123;
                                              logger.warn&#40;
                                                  "ACEGI_SECURITY_CONTEXT did not contain a Context but contained&#58; '"
                                                  + contextObject
                                                  + "'; are you improperly modifying the PortletSession directly &#40;you should always use ContextHolder&#41; or using the PortletSession attribute reserved for this class?"&#41;;
                                          &#125;
                                      &#125;
                                  &#125; else &#123;
                                      if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
                                          logger.debug&#40;
                                              "PortletSession returned null object for ACEGI_SECURITY_CONTEXT"&#41;;
                                      &#125;
                                  &#125;
                              &#125; else &#123;
                                  if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
                                      logger.debug&#40;"No PortletSession currently exists"&#41;;
                                  &#125;
                              &#125;
                      
                              if &#40;ContextHolder.getContext&#40;&#41; == null&#41; &#123;
                                  ContextHolder.setContext&#40;generateNewContext&#40;&#41;&#41;;
                      
                                  if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
                                      logger.debug&#40;
                                          "As ContextHolder null, setup ContextHolder with a fresh new instance&#58; '"
                                          + ContextHolder.getContext&#40;&#41; + "'"&#41;;
                                  &#125;
                              &#125;
                      
                              request.setAttribute&#40;SESSION_EXISTED, new Boolean&#40;portletSessionExistedAtStartOfRequest&#41;&#41;;
                      
                              return true;
                      	&#125;
                      
                      	/* &#40;non-Javadoc&#41;
                      	 * @see org.springframework.web.portlet.HandlerInterceptor#postHandle&#40;javax.portlet.RenderRequest, javax.portlet.RenderResponse, java.lang.Object, org.springframework.web.servlet.ModelAndView&#41;
                      	 */
                      	public void postHandle&#40;RenderRequest request, RenderResponse response,
                      			Object handler, ModelAndView modelAndView&#41; throws Exception &#123;
                      	&#125;
                      
                      	
                      	/* &#40;non-Javadoc&#41;
                      	 * @see org.springframework.web.portlet.HandlerInterceptor#afterCompletion&#40;javax.portlet.PortletRequest, javax.portlet.PortletResponse, java.lang.Object, java.lang.Exception&#41;
                      	 */
                      	public void afterCompletion&#40;PortletRequest request, PortletResponse response,
                      			Object handler, Exception ex&#41; throws Exception &#123;
                      		
                              PortletSession portletSession = null;
                              boolean portletSessionExistedAtStartOfRequest = &#40;&#40;Boolean&#41;request.getAttribute&#40;SESSION_EXISTED&#41;&#41;.booleanValue&#40;&#41;;
                      
                              // Store context back to PortletSession
                              try &#123;
                                  portletSession = request.getPortletSession&#40;false&#41;;
                              &#125; catch &#40;IllegalStateException ignored&#41; &#123;&#125;
                      
                              if &#40;&#40;portletSession == null&#41; && portletSessionExistedAtStartOfRequest&#41; &#123;
                                  if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
                                      logger.debug&#40;
                                          "PortletSession is now null, but was not null at start of request; session was invalidated, so do not create a new session"&#41;;
                                  &#125;
                              &#125;
                      
                              // Generate a PortletSession only if we need to
                              if &#40;&#40;portletSession == null&#41; && !portletSessionExistedAtStartOfRequest&#41; &#123;
                                  if &#40;!allowSessionCreation&#41; &#123;
                                      if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
                                          logger.debug&#40;
                                              "Whilst ContextHolder contents have changed, the PortletSessionContextIntegrationInterceptor is prohibited from creating a PortletSession by the allowSessionCreation property being false"&#41;;
                                      &#125;
                                  &#125; else if &#40;!contextObject.equals&#40;ContextHolder.getContext&#40;&#41;&#41;&#41; &#123;
                                      if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
                                          logger.debug&#40;
                                              "PortletSession being created as ContextHolder contents are non-default"&#41;;
                                      &#125;
                      
                                      try &#123;
                                          portletSession = request.getPortletSession&#40;true&#41;;
                                      &#125; catch &#40;IllegalStateException ignored&#41; &#123;&#125;
                                  &#125; else &#123;
                                      if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
                                          logger.debug&#40;
                                              "PortletSession still null, but ContextHolder has not changed from default&#58; ' "
                                              + ContextHolder.getContext&#40;&#41;
                                              + "'; not creating PortletSession or storing ContextHolder contents"&#41;;
                                      &#125;
                                  &#125;
                              &#125;
                      
                              // If PortletSession exists, store current ContextHolder contents
                              if &#40;portletSession != null&#41; &#123;
                                  portletSession.setAttribute&#40;ACEGI_SECURITY_CONTEXT_KEY,
                                      ContextHolder.getContext&#40;&#41;, PortletSession.APPLICATION_SCOPE&#41;;
                      
                                  if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
                                      logger.debug&#40;"Context stored to PortletSession&#58; '"
                                          + ContextHolder.getContext&#40;&#41; + "'"&#41;;
                                  &#125;
                              &#125;
                      
                              // Remove ContextHolder contents
                              ContextHolder.setContext&#40;null&#41;;
                      
                              if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
                                  logger.debug&#40;
                                      "ContextHolder set to null as request processing completed"&#41;;
                              &#125;
                      
                      	&#125;
                      
                      	
                          public Context generateNewContext&#40;&#41; throws PortletException &#123;
                              try &#123;
                                  return &#40;Context&#41; this.context.newInstance&#40;&#41;;
                              &#125; catch &#40;InstantiationException ie&#41; &#123;
                                  throw new PortletException&#40;ie&#41;;
                              &#125; catch &#40;IllegalAccessException iae&#41; &#123;
                                  throw new PortletException&#40;iae&#41;;
                              &#125;
                          &#125;
                      
                      &#125;
                      Here is an interface that all our controllers implement that allows us to specify the required roles for executing the controller. I don't love this part of our current configuration, but it works for now.

                      Code:
                      package com.arcanumintl.portlet.acegi;
                      
                      import java.util.Set;
                      
                      public interface SecurePortletController
                      		extends org.springframework.web.portlet.mvc.PortletController &#123;
                      
                          public void setRequiredAuthorities&#40;String requiredAuthorities&#41;;
                          
                          public Set getRequiredAuthoritiesSet&#40;&#41;;
                      
                      &#125;
                      Finally, here is the SecurityEnforcementInterceptor that enforces the definitions defined by the SecurePortletController interface. This can easily be modified to support some other way to control the list of required roles.

                      Code:
                      package com.arcanumintl.portlet.acegi;
                      
                      import java.util.Collection;
                      import java.util.Arrays;
                      import java.util.Set;
                      
                      import javax.portlet.PortletRequest;
                      import javax.portlet.PortletResponse;
                      import javax.portlet.PortletSecurityException;
                      import javax.portlet.RenderRequest;
                      import javax.portlet.RenderResponse;
                      
                      import net.sf.acegisecurity.Authentication;
                      import net.sf.acegisecurity.AuthenticationException;
                      
                      import net.sf.acegisecurity.AuthenticationManager;
                      import net.sf.acegisecurity.context.Context;
                      import net.sf.acegisecurity.context.ContextHolder;
                      import net.sf.acegisecurity.context.security.SecureContext;
                      import net.sf.acegisecurity.context.security.SecureContextImpl;
                      import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
                      
                      import org.apache.commons.logging.Log;
                      import org.apache.commons.logging.LogFactory;
                      import org.springframework.beans.factory.InitializingBean;
                      import org.springframework.web.portlet.HandlerInterceptor;
                      import org.springframework.web.servlet.ModelAndView;
                      
                      public class SecurityEnforcementInterceptor implements
                      		HandlerInterceptor, InitializingBean &#123;
                      
                          private static final Log logger = LogFactory.getLog&#40;SecurityEnforcementInterceptor.class&#41;;
                      
                          private AuthenticationManager authenticationManager;
                          private Class secureContext = SecureContextImpl.class;
                          
                          public void afterPropertiesSet&#40;&#41; throws Exception &#123;
                              if &#40;this.authenticationManager == null&#41;
                                  throw new IllegalArgumentException&#40;"An AuthenticationManager is required"&#41;;
                          &#125;
                      
                          //TODO&#58; Covert this &#40;and supporting classes&#41; to support ObjectDefinitionSource
                          //      and AbstractSecurityInterceptor -- would allow use of voters
                          
                          public boolean preHandle&#40;PortletRequest request, PortletResponse response,
                      			Object handler&#41; throws Exception &#123;
                      
                              // See if the controller is a secure controller
                              if &#40;!&#40;handler instanceof SecurePortletController&#41;&#41;
                                  return true;
                              
                          	// Get the required Authorities list for this controller
                              SecurePortletController secureHandler = &#40;SecurePortletController&#41;handler;
                      	    Set requiredAuthorities = secureHandler.getRequiredAuthoritiesSet&#40;&#41;;
                              if &#40;logger.isDebugEnabled&#40;&#41;&#41;
                                  logger.debug&#40;"Roles Required&#58; " + requiredAuthorities&#41;;
                      	    
                      	    if &#40;requiredAuthorities != null && !requiredAuthorities.isEmpty&#40;&#41;&#41; &#123;
                      	    
                      	    	// Create Authentication Request
                      	    	PortalUser portalUser = new PortalUser&#40;request&#41;;
                                  if &#40;portalUser.getUserName&#40;&#41; == null&#41;
                                  	throw new PortletSecurityException&#40;"No Portal User Defined"&#41;;
                                  UsernamePasswordAuthenticationToken authRequest = 
                      	        		new UsernamePasswordAuthenticationToken&#40;portalUser.getUserName&#40;&#41;, portalUser&#41;;
                      
                      	        // Check Authentication
                      	        Authentication authResult;
                      	        try &#123;
                      	            authResult = authenticationManager.authenticate&#40;authRequest&#41;;
                      	        &#125; catch &#40;AuthenticationException failed&#41; &#123;
                      	            // Authentication Failed
                      	            if &#40;logger.isDebugEnabled&#40;&#41;&#41;
                      	                logger.debug&#40;"Authentication request for user&#58; " + portalUser.getUserName&#40;&#41; + " failed&#58; " + failed.toString&#40;&#41;&#41;;
                      	            throw new PortletSecurityException&#40;"User Authentication Failed", failed&#41;;
                      	        &#125;
                      	        authResult.setAuthenticated&#40;true&#41;;
                      	
                      	        // Check Authorization
                      	        Collection grantedAuthorities = Arrays.asList&#40;authResult.getAuthorities&#40;&#41;&#41;;
                      	        if &#40;!grantedAuthorities.containsAll&#40;requiredAuthorities&#41;&#41; &#123;
                      	        	// Authorization Failed
                      	        	if &#40;logger.isDebugEnabled&#40;&#41;&#41;
                      	                logger.debug&#40;"Authorization request for user&#58; " + portalUser.getUserName&#40;&#41; + " failed." + "Required Authorities&#58;" + requiredAuthorities + " Granted Authorities&#58;" + grantedAuthorities&#41;;
                      	            throw new PortletSecurityException&#40;"User Not Authorized for This Action"&#41;;
                      	        &#125;
                      	        
                      	        // Authentication & Authorization success
                      	        SecureContext secureContextObject = &#40;SecureContext&#41;secureContext.newInstance&#40;&#41;;
                      	        secureContextObject.setAuthentication&#40;authResult&#41;;
                      	       	ContextHolder.setContext&#40;secureContextObject&#41;;
                      
                      	       	if &#40;logger.isDebugEnabled&#40;&#41;&#41;
                      	            logger.debug&#40;"Authentication success&#58; " + authResult.toString&#40;&#41;&#41;;
                      	    	
                      	    &#125; else &#123;
                      
                      	    	if &#40;logger.isDebugEnabled&#40;&#41;&#41;
                      	    		logger.debug&#40;"Public request - authentication not attempted"&#41;;
                      
                      	    	// Set Authentication object &#40;if it exists&#41; to be unauthenticated
                      	    	if &#40;&#40;ContextHolder.getContext&#40;&#41; != null&#41;
                      	    			&& ContextHolder.getContext&#40;&#41; instanceof SecureContext&#41; &#123;
                      	    		SecureContext context = &#40;SecureContext&#41; ContextHolder.getContext&#40;&#41;;
                      	    		if &#40;context.getAuthentication&#40;&#41; != null&#41; &#123;
                      	    			if &#40;logger.isDebugEnabled&#40;&#41;&#41;
                                              logger.debug&#40;"Authentication object detected and tagged as unauthenticated"&#41;;
                      	    			Authentication authenticated = context.getAuthentication&#40;&#41;;
                      	    			authenticated.setAuthenticated&#40;false&#41;;
                      	    			context.setAuthentication&#40;authenticated&#41;;
                      	    			ContextHolder.setContext&#40;&#40;Context&#41;context&#41;;
                                      &#125;
                                  &#125;
                      	    &#125;
                      	    
                      	    return true;
                          &#125;
                      
                      	public void postHandle&#40;RenderRequest request, RenderResponse response,
                      			Object handler, ModelAndView modelAndView&#41; throws Exception &#123;
                      	&#125;
                      
                      	public void afterCompletion&#40;PortletRequest request, PortletResponse response,
                      			Object handler, Exception ex&#41; throws Exception &#123;
                      	&#125;
                      
                          public void setAuthenticationManager&#40;AuthenticationManager authenticationManager&#41; &#123;
                              this.authenticationManager = authenticationManager;
                          &#125;
                          
                      	public void setSecureContext&#40;Class secureContext&#41; &#123;
                      		this.secureContext = secureContext;
                      	&#125;
                      &#125;

                      Comment


                      • #12
                        Very interested in thread &amp; how it applies to sun portal

                        Very interested in thread & how it applies to sun portal. What's the status of this integration in main branch.

                        Comment


                        • #13
                          This was all developed to be generic to the JSR-168 spec, so it should work with Sun Portal without any issues. The only thing I would verify in advance is the USER_INFO attributes that it supports and that the names are consistent with what is in the PortalUser class -- this can easily be changed or genericized to support other portals.

                          I have not hear anything from Ben since posting this, so I don't know what his interest level is in incorporating this into Acegi. Once the Portlet MVC framework is formally part of Spring 1.3, this will probably be worth pursuing again.

                          Comment


                          • #14
                            Originally posted by johnalewis
                            I have not hear anything from Ben since posting this, so I don't know what his interest level is in incorporating this into Acegi. Once the Portlet MVC framework is formally part of Spring 1.3, this will probably be worth pursuing again.
                            Sorry, I have been on-site consulting for the best part of the month.

                            The implementation looks like a good start. I'd recommend replacing PortletSessionContextIntegrationInterceptor with a filter instead, though, as per all other authentication mechanisms. That way you don't need to worry about HttpSession management, which has a lot of gotchas due to subtle container inconsistencies. Also, I'd not subclass DaoAuthenticationProvider but make your own implementation of AuthenticationProvider. This is just to be consistent with all the other AuthenticationProviders. You can still use the AuthenticationDao, just like say the CAS and X509 AuthenticationProviders do.

                            I would be interested in incorporating this into Acegi Security once Portlet support is formally in Spring and if there are unit tests and docs. Do you have any unit tests for your classes?

                            Comment


                            • #15
                              Thanks for the feedback.

                              Unfortunately, Servlet Filters do not apply to Portlet requests -- that is the reason for the Interceptor implementation. Hopefully usage of PortletSession will not run into the same gotchas. I've tested it in three different portlet containers and haven't seen any problems so far.

                              The reason I subclassed DaoAuthenticationProvider is that our current environment also has its own login/password table that we use for some servlet content. With this implementation, we can use the one provider to for both cases. You are right that this would not be a good choice for a generic implementation -- we should certainly do as you recommend for anything that would become part of Acegi.

                              The unit tests we have now are for our "SecurityService" layer and so they exist at a higher level than would be appropriate for integration into Acegi itself. This will need to be worked out for incorporation into Acegi.

                              I am working with Juergen to get the Portlet support completed for Spring 1.3. Everything is done except for the chapter for the reference doc, which I am working on now. Once Spring 1.3 is released, I can start looking at a more formal version of these classes that would be fit for integration into Acegi.

                              I also want to look at enhancing the simple SecurityEnforcementInterceptor I built to use ObjectDefinitionSource and AbstractSecurityInterceptor so that it will support the use of Voters, which it does not currently.

                              I'll keep you posted once I get time to work on this some more -- hopefully next month.

                              Comment

                              Working...
                              X