Clover coverage report - Acegi Security System for Spring - JBoss adapter - 1.0.0-RC1
Coverage timestamp: Mon Dec 5 2005 09:07:58 EST
file stats: LOC: 324   Methods: 5
NCLOC: 222   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
JbossAcegiLoginModule.java 55% 72.2% 100% 67.2%
coverage coverage
 1    /* Copyright 2004, 2005 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.adapters.jboss;
 17   
 18    import org.acegisecurity.AccountExpiredException;
 19    import org.acegisecurity.Authentication;
 20    import org.acegisecurity.AuthenticationException;
 21    import org.acegisecurity.AuthenticationManager;
 22    import org.acegisecurity.CredentialsExpiredException;
 23   
 24    import org.acegisecurity.adapters.PrincipalAcegiUserToken;
 25   
 26    import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
 27   
 28    import org.jboss.security.SimpleGroup;
 29    import org.jboss.security.SimplePrincipal;
 30    import org.jboss.security.auth.spi.AbstractServerLoginModule;
 31   
 32    import org.springframework.beans.factory.access.*;
 33    import org.springframework.beans.factory.access.SingletonBeanFactoryLocator;
 34   
 35    import org.springframework.context.support.ClassPathXmlApplicationContext;
 36   
 37    import java.security.Principal;
 38    import java.security.acl.Group;
 39   
 40    import java.util.Map;
 41   
 42    import javax.security.auth.Subject;
 43    import javax.security.auth.callback.Callback;
 44    import javax.security.auth.callback.CallbackHandler;
 45    import javax.security.auth.callback.NameCallback;
 46    import javax.security.auth.callback.PasswordCallback;
 47    import javax.security.auth.callback.UnsupportedCallbackException;
 48    import javax.security.auth.login.FailedLoginException;
 49    import javax.security.auth.login.LoginException;
 50   
 51   
 52    /**
 53    * Adapter to enable JBoss to authenticate via the Acegi Security System for
 54    * Spring.
 55    *
 56    * <p>
 57    * Returns a {@link PrincipalAcegiUserToken} to JBoss' authentication system,
 58    * which is subsequently available from
 59    * <code>java:comp/env/security/subject</code>.
 60    * </p>
 61    *
 62    * @author Ben Alex
 63    * @author Sergio Bern�
 64    * @version $Id: JbossAcegiLoginModule.java,v 1.11 2005/11/25 00:26:30 benalex Exp $
 65    */
 66    public class JbossAcegiLoginModule extends AbstractServerLoginModule {
 67    //~ Instance fields ========================================================
 68   
 69    private AuthenticationManager authenticationManager;
 70    private Principal identity;
 71    private String key;
 72    private char[] credential;
 73   
 74    //~ Methods ================================================================
 75   
 76  15 public void initialize(Subject subject, CallbackHandler callbackHandler,
 77    Map sharedState, Map options) {
 78  15 super.initialize(subject, callbackHandler, sharedState, options);
 79   
 80  15 if (super.log.isInfoEnabled()) {
 81  0 super.log.info("initializing jboss login module");
 82    }
 83   
 84  15 this.key = (String) options.get("key");
 85   
 86  15 if ((key == null) || "".equals(key)) {
 87  2 throw new IllegalArgumentException("key must be defined");
 88    }
 89   
 90  13 String singletonId = (String) options.get("singletonId");
 91   
 92  13 String appContextLocation = (String) options.get("appContextLocation");
 93   
 94  13 if ((((singletonId == null) || "".equals(singletonId))
 95    && (appContextLocation == null)) || "".equals(appContextLocation)) {
 96  2 throw new IllegalArgumentException(
 97    "appContextLocation must be defined");
 98    }
 99   
 100  11 String beanName = (String) options.get("authenticationManager");
 101   
 102    // Attempt to find the appContextLocation only if no singletonId was defined
 103  11 if ((singletonId == null) || "".equals(singletonId)) {
 104  11 if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) {
 105  1 if (super.log.isInfoEnabled()) {
 106  0 super.log.info("cannot locate " + appContextLocation);
 107    }
 108   
 109  1 throw new IllegalArgumentException("Cannot locate "
 110    + appContextLocation);
 111    }
 112    }
 113   
 114  10 ClassPathXmlApplicationContext ctx = null;
 115   
 116  10 if ((singletonId == null) || "".equals(singletonId)) {
 117  10 try {
 118  10 ctx = new ClassPathXmlApplicationContext(appContextLocation);
 119    } catch (Exception e) {
 120  0 if (super.log.isInfoEnabled()) {
 121  0 super.log.info("error loading spring context "
 122    + appContextLocation + " " + e);
 123    }
 124   
 125  0 throw new IllegalArgumentException(
 126    "error loading spring context " + appContextLocation + " "
 127    + e);
 128    }
 129    } else {
 130  0 if (super.log.isInfoEnabled()) {
 131  0 super.log.debug("retrieving singleton instance " + singletonId);
 132    }
 133   
 134  0 BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance();
 135  0 BeanFactoryReference bf = bfl.useBeanFactory(singletonId);
 136  0 ctx = (ClassPathXmlApplicationContext) bf.getFactory();
 137   
 138  0 if (ctx == null) {
 139  0 if (super.log.isInfoEnabled()) {
 140  0 super.log.info("singleton " + beanName + " does not exists");
 141    }
 142   
 143  0 throw new IllegalArgumentException("singleton " + singletonId
 144    + " does not exists");
 145    }
 146    }
 147   
 148  10 if ((beanName == null) || "".equals(beanName)) {
 149  10 Map beans = null;
 150   
 151  10 try {
 152  10 beans = ctx.getBeansOfType(AuthenticationManager.class, true,
 153    true);
 154    } catch (Exception e) {
 155  0 if (super.log.isInfoEnabled()) {
 156  0 super.log.info("exception in getBeansOfType " + e);
 157    }
 158   
 159  0 throw new IllegalStateException(
 160    "spring error in get beans by class");
 161    }
 162   
 163  10 if (beans.size() == 0) {
 164  1 throw new IllegalArgumentException(
 165    "Bean context must contain at least one bean of type AuthenticationManager");
 166    }
 167   
 168  9 beanName = (String) beans.keySet().iterator().next();
 169    }
 170   
 171  9 authenticationManager = (AuthenticationManager) ctx.getBean(beanName);
 172   
 173  9 if (super.log.isInfoEnabled()) {
 174  0 super.log.info("Successfully started JbossSpringLoginModule");
 175    }
 176    }
 177   
 178  8 public boolean login() throws LoginException {
 179  8 super.loginOk = false;
 180   
 181  8 String[] info = getUsernameAndPassword();
 182  7 String username = info[0];
 183  7 String password = info[1];
 184   
 185  7 if ((username == null) && (password == null)) {
 186  1 identity = null;
 187  1 super.log.trace("Authenticating as unauthenticatedIdentity="
 188    + identity);
 189    }
 190   
 191  7 if (username == null) {
 192  2 username = "";
 193    }
 194   
 195  7 if (password == null) {
 196  2 password = "";
 197    }
 198   
 199  7 if (super.log.isDebugEnabled()) {
 200  0 super.log.debug("checking identity");
 201    }
 202   
 203  7 if (identity == null) {
 204  7 super.log.debug("creating usernamepassword token");
 205   
 206  7 Authentication request = new UsernamePasswordAuthenticationToken(username,
 207    password);
 208  7 Authentication response = null;
 209   
 210  7 try {
 211  7 if (super.log.isDebugEnabled()) {
 212  0 super.log.debug("attempting authentication");
 213    }
 214   
 215  7 response = authenticationManager.authenticate(request);
 216   
 217  2 if (super.log.isDebugEnabled()) {
 218  0 super.log.debug("authentication succeded");
 219    }
 220    } catch (CredentialsExpiredException cee) {
 221  0 if (super.log.isDebugEnabled()) {
 222  0 super.log.debug("Credential has expired");
 223    }
 224   
 225  0 throw new javax.security.auth.login.CredentialExpiredException(
 226    "The credential used to identify the user has expired");
 227    } catch (AccountExpiredException cee) {
 228  0 if (super.log.isDebugEnabled()) {
 229  0 super.log.debug(
 230    "Account has expired, throwing jaas exception");
 231    }
 232   
 233  0 throw new javax.security.auth.login.AccountExpiredException(
 234    "The account specified in login has expired");
 235    } catch (AuthenticationException failed) {
 236  5 if (super.log.isDebugEnabled()) {
 237  0 super.log.debug("Bad password for username=" + username);
 238    }
 239   
 240  5 throw new FailedLoginException(
 241    "Password Incorrect/Password Required");
 242    }
 243   
 244  2 super.log.debug("user is logged. redirecting to jaas classes");
 245   
 246  2 identity = new PrincipalAcegiUserToken(this.key,
 247    response.getName(), response.getCredentials().toString(),
 248    response.getAuthorities(), response.getPrincipal());
 249    }
 250   
 251  2 if (getUseFirstPass() == true) {
 252    // Add the username and password to the shared state map
 253  0 sharedState.put("javax.security.auth.login.name", username);
 254  0 sharedState.put("javax.security.auth.login.password", credential);
 255    }
 256   
 257  2 super.loginOk = true;
 258  2 super.log.trace("User '" + identity + "' authenticated, loginOk="
 259    + loginOk);
 260   
 261  2 return true;
 262    }
 263   
 264  1 protected Principal getIdentity() {
 265  1 return this.identity;
 266    }
 267   
 268  1 protected Group[] getRoleSets() throws LoginException {
 269  1 SimpleGroup roles = new SimpleGroup("Roles");
 270  1 Group[] roleSets = {roles};
 271   
 272  1 if (this.identity instanceof Authentication) {
 273  1 Authentication user = (Authentication) this.identity;
 274   
 275  1 for (int i = 0; i < user.getAuthorities().length; i++) {
 276  2 roles.addMember(new SimplePrincipal(
 277    user.getAuthorities()[i].getAuthority()));
 278    }
 279    }
 280   
 281  1 return roleSets;
 282    }
 283   
 284  8 protected String[] getUsernameAndPassword() throws LoginException {
 285  8 String[] info = {null, null};
 286   
 287    // prompt for a username and password
 288  8 if (callbackHandler == null) {
 289  1 throw new LoginException("Error: no CallbackHandler available "
 290    + "to collect authentication information");
 291    }
 292   
 293  7 NameCallback nc = new NameCallback("User name: ", "guest");
 294  7 PasswordCallback pc = new PasswordCallback("Password: ", false);
 295  7 Callback[] callbacks = {nc, pc};
 296  7 String username = null;
 297  7 String password = null;
 298   
 299  7 try {
 300  7 callbackHandler.handle(callbacks);
 301  7 username = nc.getName();
 302   
 303  7 char[] tmpPassword = pc.getPassword();
 304   
 305  7 if (tmpPassword != null) {
 306  5 credential = new char[tmpPassword.length];
 307  5 System.arraycopy(tmpPassword, 0, credential, 0,
 308    tmpPassword.length);
 309  5 pc.clearPassword();
 310  5 password = new String(credential);
 311    }
 312    } catch (java.io.IOException ioe) {
 313  0 throw new LoginException(ioe.toString());
 314    } catch (UnsupportedCallbackException uce) {
 315  0 throw new LoginException("CallbackHandler does not support: "
 316    + uce.getCallback());
 317    }
 318   
 319  7 info[0] = username;
 320  7 info[1] = password;
 321   
 322  7 return info;
 323    }
 324    }