Coverage Report - org.acegisecurity.providers.jaas.SecurityContextLoginModule
 
Classes in this File Line Coverage Branch Coverage Complexity
SecurityContextLoginModule
93% 
100% 
2.571
 
 1  
 /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
 2  
  *
 3  
  * Licensed under the Apache License, Version 2.0 (the "License");
 4  
  * you may not use this file except in compliance with the License.
 5  
  * You may obtain a copy of the License at
 6  
  *
 7  
  *     http://www.apache.org/licenses/LICENSE-2.0
 8  
  *
 9  
  * Unless required by applicable law or agreed to in writing, software
 10  
  * distributed under the License is distributed on an "AS IS" BASIS,
 11  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  
  * See the License for the specific language governing permissions and
 13  
  * limitations under the License.
 14  
  */
 15  
 
 16  
 package org.acegisecurity.providers.jaas;
 17  
 
 18  
 import org.acegisecurity.Authentication;
 19  
 
 20  
 import org.acegisecurity.context.SecurityContextHolder;
 21  
 
 22  
 import org.apache.commons.logging.Log;
 23  
 import org.apache.commons.logging.LogFactory;
 24  
 
 25  
 import java.util.Map;
 26  
 
 27  
 import javax.security.auth.Subject;
 28  
 import javax.security.auth.callback.CallbackHandler;
 29  
 import javax.security.auth.login.LoginException;
 30  
 import javax.security.auth.spi.LoginModule;
 31  
 
 32  
 
 33  
 /**
 34  
  * An implementation of {@link LoginModule} that uses an Acegi Security {@link
 35  
  * org.acegisecurity.context.SecurityContext SecurityContext} to provide authentication.<p>This LoginModule
 36  
  * provides opposite functionality to the {@link JaasAuthenticationProvider} API, and should not really be used in
 37  
  * conjunction with it.</p>
 38  
  *  <p>The {@link JaasAuthenticationProvider} allows Acegi to authenticate against Jaas.</p>
 39  
  *  <p>The SecurityContextLoginModule allows a Jaas based application to authenticate against Acegi. If there is no
 40  
  * Authentication in the  {@link SecurityContextHolder} the login() method will throw a LoginException by default.
 41  
  * This functionality can be changed with the <tt>ignoreMissingAuthentication</tt> option by setting it to "true".
 42  
  * Setting ignoreMissingAuthentication=true will tell the SecurityContextLoginModule to simply return false and be
 43  
  * ignored if the authentication is null.</p>
 44  
  *
 45  
  * @author Brian Moseley
 46  
  * @author Ray Krueger
 47  
  */
 48  8
 public class SecurityContextLoginModule implements LoginModule {
 49  
     //~ Static fields/initializers =====================================================================================
 50  
 
 51  2
     private static final Log log = LogFactory.getLog(SecurityContextLoginModule.class);
 52  
 
 53  
     //~ Instance fields ================================================================================================
 54  
 
 55  
     private Authentication authen;
 56  
     private Subject subject;
 57  8
     private boolean ignoreMissingAuthentication = false;
 58  
 
 59  
     //~ Methods ========================================================================================================
 60  
 
 61  
     /**
 62  
      * Abort the authentication process by forgetting the Acegi Security <code>Authentication</code>.
 63  
      *
 64  
      * @return true if this method succeeded, or false if this <code>LoginModule</code> should be ignored.
 65  
      *
 66  
      * @exception LoginException if the abort fails
 67  
      */
 68  
     public boolean abort() throws LoginException {
 69  2
         if (authen == null) {
 70  1
             return false;
 71  
         }
 72  
 
 73  1
         authen = null;
 74  
 
 75  1
         return true;
 76  
     }
 77  
 
 78  
     /**
 79  
      * Authenticate the <code>Subject</code> (phase two) by adding the Acegi Security
 80  
      * <code>Authentication</code> to the <code>Subject</code>'s principals.
 81  
      *
 82  
      * @return true if this method succeeded, or false if this <code>LoginModule</code> should be ignored.
 83  
      *
 84  
      * @exception LoginException if the commit fails
 85  
      */
 86  
     public boolean commit() throws LoginException {
 87  2
         if (authen == null) {
 88  0
             return false;
 89  
         }
 90  
 
 91  2
         subject.getPrincipals().add(authen);
 92  
 
 93  2
         return true;
 94  
     }
 95  
 
 96  
     Authentication getAuthentication() {
 97  1
         return authen;
 98  
     }
 99  
 
 100  
     Subject getSubject() {
 101  0
         return subject;
 102  
     }
 103  
 
 104  
     /**
 105  
      * Initialize this <code>LoginModule</code>. Ignores the callback handler, since the code establishing the
 106  
      * <code>LoginContext</code> likely won't provide one that understands Acegi Security. Also ignores the
 107  
      * <code>sharedState</code> and <code>options</code> parameters, since none are recognized.
 108  
      *
 109  
      * @param subject the <code>Subject</code> to be authenticated. <p>
 110  
      * @param callbackHandler is ignored
 111  
      * @param sharedState is ignored
 112  
      * @param options are ignored
 113  
      */
 114  
     public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
 115  8
         this.subject = subject;
 116  
 
 117  8
         if (options != null) {
 118  1
             ignoreMissingAuthentication = "true".equals(options.get("ignoreMissingAuthentication"));
 119  
         }
 120  8
     }
 121  
 
 122  
     /**
 123  
      * Authenticate the <code>Subject</code> (phase one) by extracting the Acegi Security
 124  
      * <code>Authentication</code> from the current <code>SecurityContext</code>.
 125  
      *
 126  
      * @return true if the authentication succeeded, or false if this <code>LoginModule</code> should be ignored.
 127  
      *
 128  
      * @throws LoginException if the authentication fails
 129  
      */
 130  
     public boolean login() throws LoginException {
 131  6
         authen = SecurityContextHolder.getContext().getAuthentication();
 132  
 
 133  6
         if (authen == null) {
 134  3
             String msg = "Login cannot complete, authentication not found in security context";
 135  
 
 136  3
             if (ignoreMissingAuthentication) {
 137  1
                 log.warn(msg);
 138  
 
 139  1
                 return false;
 140  
             } else {
 141  2
                 throw new LoginException(msg);
 142  
             }
 143  
         }
 144  
 
 145  3
         return true;
 146  
     }
 147  
 
 148  
     /**
 149  
      * Log out the <code>Subject</code>.
 150  
      *
 151  
      * @return true if this method succeeded, or false if this <code>LoginModule</code> should be ignored.
 152  
      *
 153  
      * @exception LoginException if the logout fails
 154  
      */
 155  
     public boolean logout() throws LoginException {
 156  2
         if (authen == null) {
 157  1
             return false;
 158  
         }
 159  
 
 160  1
         subject.getPrincipals().remove(authen);
 161  1
         authen = null;
 162  
 
 163  1
         return true;
 164  
     }
 165  
 }