Announcement Announcement Module
Collapse
No announcement yet.
acegi not calling JAAS LoginModule.logout() anywhere? Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • acegi not calling JAAS LoginModule.logout() anywhere?

    I can't seem to find anywhere any Acegi code that supports logout in a JAAS environment.

    What I'm looking for is something along the lines of code that listens for HttpSessionDestroyedEvent from HttpSessionEventPublisher.sessionDestroyed(), which then calls LoginContext.logout() so that the configured LoginModules have their respective logout() methods called.

    On a related note, the JaasAuthenticationProvider.authenticate() creates a new LoginContext on every invocation. Why is this? The provider itself is only created once since it's a spring bean. The same provider is used for all authentication requests, right?

    The problem I see with creating a new LoginContext every time is that there's no ability to use instance variables in the LoginModules. Most LoginModule implementations I've seen shared state across login() and logout() to know if a user was logged in for example. Here's some code from the JDK's JndiLoginModule ...
    Code:
        public boolean logout() throws LoginException {
    	if (subject.isReadOnly()) {
    	    cleanState();
    	    throw new LoginException ("Subject is Readonly");
    	}
    	subject.getPrincipals().remove(userPrincipal);
    	subject.getPrincipals().remove(UIDPrincipal);
    	subject.getPrincipals().remove(GIDPrincipal);
    	for &#40;int i = 0; i < supplementaryGroups.size&#40;&#41;; i++&#41; &#123;
    	    subject.getPrincipals&#40;&#41;.remove
    		&#40;&#40;UnixNumericGroupPrincipal&#41;supplementaryGroups.get&#40;i&#41;&#41;;
    	&#125;
        
        
    	// clean out state
    	cleanState&#40;&#41;;
    	succeeded = false;
    	commitSucceeded = false;
    
    	userPrincipal = null;
    	UIDPrincipal = null;
    	GIDPrincipal = null;
    	supplementaryGroups = new LinkedList&#40;&#41;;
    
    	if &#40;debug&#41; &#123;
    	    System.out.println&#40;"\t\t&#91;JndiLoginModule&#93;&#58; " +
    		"logged out Subject"&#41;;
    	&#125;
    	return true;
        &#125;
    I appologize in advance if I'm being obstuse and missing something in the way that JAAS and/or Acegi work.

    Thanks for the help.

  • #2
    Acegi Security does not offer a logout function. There are past threads here in the forum that discuss this some more.

    In relation to the JAAS integration, that is maintained by Ray Krueger who is currently relocating. If you post a patch, either Ray or I will apply it.

    Comment


    • #3
      Understood. I patched JaasAuthenticationProvider as follows.
      • * modify InternalCallbackHandler so that the Authentication object is provided via a setter, rather than in the constructor, so that it can be created once and reused.
        * make loginContext and callbackHandler class instance variables rather than local variables in the authenticate() method.
        * modify afterPropertiesSet() to initialize loginContext and callbackHandler
        * modify authenticate() to set the Authentication object on the callback handler
        * have the class implement ApplicationListener
        * implement ApplicationListener.onApplicationEvent() to handle HttpSessionDestroyedEvents, to call LoginContext.logout()
      As I mentioned I'm not sure if this is the best way to solve the problem but it seems to work OK.
      Code:
      *** acegisecurity/core/src/main/java/net/sf/acegisecurity/providers/jaas/JaasAuthenticationProvider.java	Tue Apr 26 20&#58;39&#58;06 2005
      --- JaasAuthenticationProvider.java.new	Mon Jun  6 14&#58;03&#58;57 2005
      ***************
      *** 19,24 ****
      --- 19,27 ----
        import net.sf.acegisecurity.Authentication;
        import net.sf.acegisecurity.AuthenticationException;
        import net.sf.acegisecurity.GrantedAuthority;
      + import net.sf.acegisecurity.context.SecurityContext;
      + import net.sf.acegisecurity.context.SecurityContextHolder;
      + import net.sf.acegisecurity.ui.session.HttpSessionDestroyedEvent;
        import net.sf.acegisecurity.providers.AuthenticationProvider;
        import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
        import net.sf.acegisecurity.providers.jaas.event.JaasAuthenticationFailedEvent;
      ***************
      *** 32,37 ****
      --- 35,42 ----
        
        import org.springframework.context.ApplicationContext;
        import org.springframework.context.ApplicationContextAware;
      + import org.springframework.context.ApplicationListener;
      + import org.springframework.context.ApplicationEvent;
        
        import org.springframework.core.io.Resource;
        
      ***************
      *** 160,166 ****
         * @version $Id&#58; JaasAuthenticationProvider.java,v 1.11 2005/04/27 03&#58;39&#58;05 raykrueger Exp $
         */
        public class JaasAuthenticationProvider implements AuthenticationProvider,
      !     InitializingBean, ApplicationContextAware &#123;
            //~ Static fields/initializers =============================================
        
            protected static final Log log = LogFactory.getLog&#40;JaasAuthenticationProvider.class&#41;;
      --- 165,171 ----
         * @version $Id&#58; JaasAuthenticationProvider.java,v 1.11 2005/04/27 03&#58;39&#58;05 raykrueger Exp $
         */
        public class JaasAuthenticationProvider implements AuthenticationProvider,
      !     InitializingBean, ApplicationContextAware, ApplicationListener &#123;
            //~ Static fields/initializers =============================================
        
            protected static final Log log = LogFactory.getLog&#40;JaasAuthenticationProvider.class&#41;;
      ***************
      *** 174,179 ****
      --- 179,186 ----
            private String loginContextName = "ACEGI";
            private AuthorityGranter&#91;&#93; authorityGranters;
            private JaasAuthenticationCallbackHandler&#91;&#93; callbackHandlers;
      +     private InternalCallbackHandler callbackHandler;
      +     private LoginContext loginContext;
        
            //~ Methods ================================================================
        
      ***************
      *** 307,312 ****
      --- 314,322 ----
        
                Assert.notNull&#40;Configuration.getConfiguration&#40;&#41;,
                    "As per http&#58;//java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/login/Configuration.html \"If a Configuration object was set via the Configuration.setConfiguration method, then that object is returned. Otherwise, a default Configuration object is returned\". Your JRE returned null to Configuration.getConfiguration&#40;&#41;."&#41;;
      + 
      +         callbackHandler = new InternalCallbackHandler&#40;&#41;;
      +         loginContext = new LoginContext&#40;loginContextName, callbackHandler&#41;;
            &#125;
        
            /**
      ***************
      *** 330,341 ****
                    UsernamePasswordAuthenticationToken token = &#40;UsernamePasswordAuthenticationToken&#41; auth;
        
                    try &#123;
      !                 //Create the LoginContext object, and pass our InternallCallbackHandler
      !                 LoginContext lc = new LoginContext&#40;loginContextName,
      !                         new InternalCallbackHandler&#40;auth&#41;&#41;;
        
                        //Attempt to login the user, the LoginContext will call our InternalCallbackHandler at this point.
      !                 lc.login&#40;&#41;;
        
                        //create a set to hold the authorities, and add any that have already been applied.
                        Set authorities = new HashSet&#40;&#41;;
      --- 340,349 ----
                    UsernamePasswordAuthenticationToken token = &#40;UsernamePasswordAuthenticationToken&#41; auth;
        
                    try &#123;
      !                 callbackHandler.setAuthentication&#40;auth&#41;;
        
                        //Attempt to login the user, the LoginContext will call our InternalCallbackHandler at this point.
      !                 loginContext.login&#40;&#41;;
        
                        //create a set to hold the authorities, and add any that have already been applied.
                        Set authorities = new HashSet&#40;&#41;;
      ***************
      *** 345,351 ****
                        &#125;
        
                        //get the subject principals and pass them to each of the AuthorityGranters
      !                 Set principals = lc.getSubject&#40;&#41;.getPrincipals&#40;&#41;;
        
                        for &#40;Iterator iterator = principals.iterator&#40;&#41;;
                            iterator.hasNext&#40;&#41;;&#41; &#123;
      --- 353,359 ----
                        &#125;
        
                        //get the subject principals and pass them to each of the AuthorityGranters
      !                 Set principals = loginContext.getSubject&#40;&#41;.getPrincipals&#40;&#41;;
        
                        for &#40;Iterator iterator = principals.iterator&#40;&#41;;
                            iterator.hasNext&#40;&#41;;&#41; &#123;
      ***************
      *** 451,456 ****
      --- 459,482 ----
                &#125;
            &#125;
        
      +     public void onApplicationEvent&#40;ApplicationEvent event&#41; &#123;
      +       if &#40;event instanceof HttpSessionDestroyedEvent&#41; &#123;
      +         SecurityContext context = &#40;SecurityContext&#41; SecurityContextHolder.getContext&#40;&#41;;
      +         if &#40;context != null&#41; &#123;
      +           try &#123;
      +             loginContext.logout&#40;&#41;;
      +           &#125;
      +           catch &#40;LoginException e&#41; &#123;
      +             AcegiSecurityException ase = loginExceptionResolver.resolveException&#40;e&#41;;
      +             log.error&#40;ase.getMessage&#40;&#41;, ase&#41;;
      +           &#125;
      +         &#125;
      +         else &#123;
      +           log.debug&#40;"onApplicationEvent - no SecureContext available"&#41;;
      +         &#125;
      +       &#125;
      +     &#125;
      + 
            //~ Inner Classes ==========================================================
        
            /**
      ***************
      *** 459,466 ****
            private class InternalCallbackHandler implements CallbackHandler &#123;
                private Authentication authentication;
        
      !         public InternalCallbackHandler&#40;Authentication authentication&#41; &#123;
      !             this.authentication = authentication;
                &#125;
        
                public void handle&#40;Callback&#91;&#93; callbacks&#41;
      --- 485,495 ----
            private class InternalCallbackHandler implements CallbackHandler &#123;
                private Authentication authentication;
        
      !         public InternalCallbackHandler&#40;&#41; &#123;
      !         &#125;
      ! 
      !         public void setAuthentication&#40;Authentication authentication&#41; &#123;
      !           this.authentication = authentication;
                &#125;
        
                public void handle&#40;Callback&#91;&#93; callbacks&#41;

      Comment


      • #4
        Would you please log your patch in JIRA: http://opensource.atlassian.com/proj....jspa?id=10040

        Thanks!

        Comment

        Working...
        X