Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: net/sf/acegisecurity/adapters/jboss/JbossAcegiLoginModule.java


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