Source Code Cross Referenced for JaasAuthenticationProvider.java in  » Security » acegi-security » org » acegisecurity » providers » jaas » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Security » acegi security » org.acegisecurity.providers.jaas 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
002:         *
003:         * Licensed under the Apache License, Version 2.0 (the "License");
004:         * you may not use this file except in compliance with the License.
005:         * You may obtain a copy of the License at
006:         *
007:         *     http://www.apache.org/licenses/LICENSE-2.0
008:         *
009:         * Unless required by applicable law or agreed to in writing, software
010:         * distributed under the License is distributed on an "AS IS" BASIS,
011:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012:         * See the License for the specific language governing permissions and
013:         * limitations under the License.
014:         */
015:
016:        package org.acegisecurity.providers.jaas;
017:
018:        import org.acegisecurity.AcegiSecurityException;
019:        import org.acegisecurity.Authentication;
020:        import org.acegisecurity.AuthenticationException;
021:        import org.acegisecurity.GrantedAuthority;
022:
023:        import org.acegisecurity.context.HttpSessionContextIntegrationFilter;
024:        import org.acegisecurity.context.SecurityContext;
025:
026:        import org.acegisecurity.providers.AuthenticationProvider;
027:        import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
028:        import org.acegisecurity.providers.jaas.event.JaasAuthenticationFailedEvent;
029:        import org.acegisecurity.providers.jaas.event.JaasAuthenticationSuccessEvent;
030:
031:        import org.acegisecurity.ui.session.HttpSessionDestroyedEvent;
032:
033:        import org.apache.commons.logging.Log;
034:        import org.apache.commons.logging.LogFactory;
035:
036:        import org.springframework.beans.BeansException;
037:        import org.springframework.beans.factory.InitializingBean;
038:
039:        import org.springframework.context.*;
040:
041:        import org.springframework.core.io.Resource;
042:
043:        import org.springframework.util.Assert;
044:
045:        import java.io.IOException;
046:
047:        import java.security.Principal;
048:        import java.security.Security;
049:
050:        import java.util.Arrays;
051:        import java.util.HashSet;
052:        import java.util.Iterator;
053:        import java.util.Set;
054:
055:        import javax.security.auth.callback.Callback;
056:        import javax.security.auth.callback.CallbackHandler;
057:        import javax.security.auth.callback.UnsupportedCallbackException;
058:        import javax.security.auth.login.Configuration;
059:        import javax.security.auth.login.LoginContext;
060:        import javax.security.auth.login.LoginException;
061:
062:        /**
063:         * An {@link AuthenticationProvider} implementation that retrieves user details from a JAAS login configuration.
064:         *
065:         * <p>This <code>AuthenticationProvider</code> is capable of validating {@link
066:         * org.acegisecurity.providers.UsernamePasswordAuthenticationToken} requests contain the correct username and
067:         * password.</p>
068:         * <p>This implementation is backed by a <a
069:         * href="http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASRefGuide.html">JAAS</a> configuration. The
070:         * loginConfig property must be set to a given JAAS configuration file. This setter accepts a Spring {@link
071:         * org.springframework.core.io.Resource} instance. It should point to a JAAS configuration file containing an index
072:         * matching the {@link #setLoginContextName(java.lang.String) loginContextName} property.
073:         * </p>
074:         * <p>
075:         * For example: If this JaasAuthenticationProvider were configured in a Spring WebApplicationContext the xml to
076:         * set the loginConfiguration could be as follows...
077:         * <pre>
078:         * &lt;property name="loginConfig"&gt;
079:         *   &lt;value&gt;/WEB-INF/login.conf&lt;/value&gt;
080:         * &lt;/property&gt;
081:         * </pre>
082:         * </p>
083:         * <p>
084:         * The loginContextName should coincide with a given index in the loginConfig specifed. The loginConfig file
085:         * used in the JUnit tests appears as the following...
086:         * <pre> JAASTest {
087:         *   org.acegisecurity.providers.jaas.TestLoginModule required;
088:         * };
089:         * </pre>
090:         * Using the example login configuration above, the loginContextName property would be set as <i>JAASTest</i>...
091:         * <pre>
092:         *  &lt;property name="loginContextName"&gt; &lt;value&gt;JAASTest&lt;/value&gt; &lt;/property&gt;
093:         * </pre>
094:         * </p>
095:         *  <p>When using JAAS login modules as the authentication source, sometimes the
096:         * <a href="http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/login/LoginContext.html">LoginContext</a> will
097:         * require <i>CallbackHandler</i>s. The JaasAuthenticationProvider uses an internal
098:         * <a href="http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/callback/CallbackHandler.html">CallbackHandler
099:         * </a> to wrap the {@link JaasAuthenticationCallbackHandler}s configured in the ApplicationContext.
100:         * When the LoginContext calls the internal CallbackHandler, control is passed to each
101:         * {@link JaasAuthenticationCallbackHandler} for each Callback passed.
102:         * </p>
103:         * <p>{@link JaasAuthenticationCallbackHandler}s are passed to the JaasAuthenticationProvider through the {@link
104:         * #setCallbackHandlers(org.acegisecurity.providers.jaas.JaasAuthenticationCallbackHandler[]) callbackHandlers}
105:         * property.
106:         * <pre>
107:         * &lt;property name="callbackHandlers"&gt;
108:         *   &lt;list&gt;
109:         *     &lt;bean class="org.acegisecurity.providers.jaas.TestCallbackHandler"/&gt;
110:         *     &lt;bean class="{@link JaasNameCallbackHandler org.acegisecurity.providers.jaas.JaasNameCallbackHandler}"/&gt;
111:         *     &lt;bean class="{@link JaasPasswordCallbackHandler org.acegisecurity.providers.jaas.JaasPasswordCallbackHandler}"/&gt;
112:         *  &lt;/list&gt;
113:         * &lt;/property&gt;
114:         * </pre>
115:         * </p>
116:         * <p>
117:         * After calling LoginContext.login(), the JaasAuthenticationProvider will retrieve the returned Principals
118:         * from the Subject (LoginContext.getSubject().getPrincipals). Each returned principal is then passed to the
119:         * configured {@link AuthorityGranter}s. An AuthorityGranter is a mapping between a returned Principal, and a role
120:         * name. If an AuthorityGranter wishes to grant an Authorization a role, it returns that role name from it's {@link
121:         * AuthorityGranter#grant(java.security.Principal)} method. The returned role will be applied to the Authorization
122:         * object as a {@link GrantedAuthority}.</p>
123:         * <p>AuthorityGranters are configured in spring xml as follows...
124:         * <pre>
125:         * &lt;property name="authorityGranters"&gt;
126:         *   &lt;list&gt;
127:         *     &lt;bean class="org.acegisecurity.providers.jaas.TestAuthorityGranter"/&gt;
128:         *   &lt;/list&gt;
129:         *  &lt;/property&gt;
130:         * </pre>
131:         * A configuration note: The JaasAuthenticationProvider uses the security properites
132:         * &quote;login.config.url.X&quote; to configure jaas. If you would like to customize the way Jaas gets configured,
133:         * create a subclass of this and override the {@link #configureJaas(Resource)} method.
134:         * </p>
135:         *
136:         * @author Ray Krueger
137:         * @version $Id: JaasAuthenticationProvider.java 1985 2007-08-29 11:51:02Z luke_t $
138:         */
139:        public class JaasAuthenticationProvider implements 
140:                AuthenticationProvider, ApplicationEventPublisherAware,
141:                InitializingBean, ApplicationListener {
142:            //~ Static fields/initializers =====================================================================================
143:
144:            protected static final Log log = LogFactory
145:                    .getLog(JaasAuthenticationProvider.class);
146:
147:            //~ Instance fields ================================================================================================
148:
149:            private LoginExceptionResolver loginExceptionResolver = new DefaultLoginExceptionResolver();
150:            private Resource loginConfig;
151:            private String loginContextName = "ACEGI";
152:            private AuthorityGranter[] authorityGranters;
153:            private JaasAuthenticationCallbackHandler[] callbackHandlers;
154:            private ApplicationEventPublisher applicationEventPublisher;
155:
156:            //~ Methods ========================================================================================================
157:
158:            public void afterPropertiesSet() throws Exception {
159:                Assert.notNull(loginConfig, "loginConfig must be set on "
160:                        + getClass());
161:                Assert.hasLength(loginContextName,
162:                        "loginContextName must be set on " + getClass());
163:
164:                configureJaas(loginConfig);
165:
166:                Assert
167:                        .notNull(
168:                                Configuration.getConfiguration(),
169:                                "As per http://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/login/Configuration.html "
170:                                        + "\"If a Configuration object was set via the Configuration.setConfiguration method, then that object is "
171:                                        + "returned. Otherwise, a default Configuration object is returned\". Your JRE returned null to "
172:                                        + "Configuration.getConfiguration().");
173:            }
174:
175:            /**
176:             * Attempts to login the user given the Authentication objects principal and credential
177:             *
178:             * @param auth The Authentication object to be authenticated.
179:             *
180:             * @return The authenticated Authentication object, with it's grantedAuthorities set.
181:             *
182:             * @throws AuthenticationException This implementation does not handle 'locked' or 'disabled' accounts. This method
183:             *         only throws a AuthenticationServiceException, with the message of the LoginException that will be
184:             *         thrown, should the loginContext.login() method fail.
185:             */
186:            public Authentication authenticate(Authentication auth)
187:                    throws AuthenticationException {
188:                if (auth instanceof  UsernamePasswordAuthenticationToken) {
189:                    UsernamePasswordAuthenticationToken request = (UsernamePasswordAuthenticationToken) auth;
190:
191:                    try {
192:                        //Create the LoginContext object, and pass our InternallCallbackHandler
193:                        LoginContext loginContext = new LoginContext(
194:                                loginContextName, new InternalCallbackHandler(
195:                                        auth));
196:
197:                        //Attempt to login the user, the LoginContext will call our InternalCallbackHandler at this point.
198:                        loginContext.login();
199:
200:                        //create a set to hold the authorities, and add any that have already been applied.
201:                        Set authorities = new HashSet();
202:
203:                        if (request.getAuthorities() != null) {
204:                            authorities.addAll(Arrays.asList(request
205:                                    .getAuthorities()));
206:                        }
207:
208:                        //get the subject principals and pass them to each of the AuthorityGranters
209:                        Set principals = loginContext.getSubject()
210:                                .getPrincipals();
211:
212:                        for (Iterator iterator = principals.iterator(); iterator
213:                                .hasNext();) {
214:                            Principal principal = (Principal) iterator.next();
215:
216:                            for (int i = 0; i < authorityGranters.length; i++) {
217:                                AuthorityGranter granter = authorityGranters[i];
218:                                Set roles = granter.grant(principal);
219:
220:                                //If the granter doesn't wish to grant any authorities, it should return null.
221:                                if ((roles != null) && !roles.isEmpty()) {
222:                                    for (Iterator roleIterator = roles
223:                                            .iterator(); roleIterator.hasNext();) {
224:                                        String role = roleIterator.next()
225:                                                .toString();
226:                                        authorities
227:                                                .add(new JaasGrantedAuthority(
228:                                                        role, principal));
229:                                    }
230:                                }
231:                            }
232:                        }
233:
234:                        //Convert the authorities set back to an array and apply it to the token.
235:                        JaasAuthenticationToken result = new JaasAuthenticationToken(
236:                                request.getPrincipal(),
237:                                request.getCredentials(),
238:                                (GrantedAuthority[]) authorities
239:                                        .toArray(new GrantedAuthority[authorities
240:                                                .size()]), loginContext);
241:
242:                        //Publish the success event
243:                        publishSuccessEvent(result);
244:
245:                        //we're done, return the token.
246:                        return result;
247:                    } catch (LoginException loginException) {
248:                        AcegiSecurityException ase = loginExceptionResolver
249:                                .resolveException(loginException);
250:
251:                        publishFailureEvent(request, ase);
252:                        throw ase;
253:                    }
254:                }
255:
256:                return null;
257:            }
258:
259:            /**
260:             * Hook method for configuring Jaas
261:             *
262:             * @param loginConfig URL to Jaas login configuration
263:             *
264:             * @throws IOException if there is a problem reading the config resource.
265:             */
266:            protected void configureJaas(Resource loginConfig)
267:                    throws IOException {
268:                configureJaasUsingLoop();
269:            }
270:
271:            /**
272:             * Loops through the login.config.url.1,login.config.url.2 properties looking for the login configuration.
273:             * If it is not set, it will be set to the last available login.config.url.X property.
274:             *
275:             */
276:            private void configureJaasUsingLoop() throws IOException {
277:                String loginConfigUrl = loginConfig.getURL().toString();
278:                boolean alreadySet = false;
279:
280:                int n = 1;
281:                String prefix = "login.config.url.";
282:                String existing = null;
283:
284:                while ((existing = Security.getProperty(prefix + n)) != null) {
285:                    alreadySet = existing.equals(loginConfigUrl);
286:
287:                    if (alreadySet) {
288:                        break;
289:                    }
290:
291:                    n++;
292:                }
293:
294:                if (!alreadySet) {
295:                    String key = prefix + n;
296:                    log.debug("Setting security property [" + key + "] to: "
297:                            + loginConfigUrl);
298:                    Security.setProperty(key, loginConfigUrl);
299:                }
300:            }
301:
302:            /**
303:             * Returns the AuthorityGrannter array that was passed to the {@link
304:             * #setAuthorityGranters(AuthorityGranter[])} method, or null if it none were ever set.
305:             *
306:             * @return The AuthorityGranter array, or null
307:             *
308:             * @see #setAuthorityGranters(AuthorityGranter[])
309:             */
310:            public AuthorityGranter[] getAuthorityGranters() {
311:                return authorityGranters;
312:            }
313:
314:            /**
315:             * Returns the current JaasAuthenticationCallbackHandler array, or null if none are set.
316:             *
317:             * @return the JAASAuthenticationCallbackHandlers.
318:             *
319:             * @see #setCallbackHandlers(JaasAuthenticationCallbackHandler[])
320:             */
321:            public JaasAuthenticationCallbackHandler[] getCallbackHandlers() {
322:                return callbackHandlers;
323:            }
324:
325:            public Resource getLoginConfig() {
326:                return loginConfig;
327:            }
328:
329:            public String getLoginContextName() {
330:                return loginContextName;
331:            }
332:
333:            public LoginExceptionResolver getLoginExceptionResolver() {
334:                return loginExceptionResolver;
335:            }
336:
337:            /**
338:             * Handles the logout by getting the SecurityContext for the session that was destroyed. <b>MUST NOT use
339:             * SecurityContextHolder we are logging out a session that is not related to the current user.</b>
340:             *
341:             * @param event
342:             */
343:            protected void handleLogout(HttpSessionDestroyedEvent event) {
344:                SecurityContext context = (SecurityContext) event
345:                        .getSession()
346:                        .getAttribute(
347:                                HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY);
348:
349:                if (context == null) {
350:                    log.debug("The destroyed session has no SecurityContext");
351:
352:                    return;
353:                }
354:
355:                Authentication auth = context.getAuthentication();
356:
357:                if ((auth != null) && (auth instanceof  JaasAuthenticationToken)) {
358:                    JaasAuthenticationToken token = (JaasAuthenticationToken) auth;
359:
360:                    try {
361:                        LoginContext loginContext = token.getLoginContext();
362:
363:                        if (loginContext != null) {
364:                            log.debug("Logging principal: ["
365:                                    + token.getPrincipal()
366:                                    + "] out of LoginContext");
367:                            loginContext.logout();
368:                        } else {
369:                            log.debug("Cannot logout principal: ["
370:                                    + token.getPrincipal()
371:                                    + "] from LoginContext. "
372:                                    + "The LoginContext is unavailable");
373:                        }
374:                    } catch (LoginException e) {
375:                        log.warn("Error error logging out of LoginContext", e);
376:                    }
377:                }
378:            }
379:
380:            public void onApplicationEvent(ApplicationEvent applicationEvent) {
381:                if (applicationEvent instanceof  HttpSessionDestroyedEvent) {
382:                    HttpSessionDestroyedEvent event = (HttpSessionDestroyedEvent) applicationEvent;
383:                    handleLogout(event);
384:                }
385:            }
386:
387:            /**
388:             * Publishes the {@link JaasAuthenticationFailedEvent}. Can be overridden by subclasses for different
389:             * functionality
390:             *
391:             * @param token The {@link UsernamePasswordAuthenticationToken} being processed
392:             * @param ase The {@link AcegiSecurityException} that caused the failure
393:             */
394:            protected void publishFailureEvent(
395:                    UsernamePasswordAuthenticationToken token,
396:                    AcegiSecurityException ase) {
397:                applicationEventPublisher
398:                        .publishEvent(new JaasAuthenticationFailedEvent(token,
399:                                ase));
400:            }
401:
402:            /**
403:             * Publishes the {@link JaasAuthenticationSuccessEvent}. Can be overridden by subclasses for different
404:             * functionality.
405:             *
406:             * @param token The {@link UsernamePasswordAuthenticationToken} being processed
407:             */
408:            protected void publishSuccessEvent(
409:                    UsernamePasswordAuthenticationToken token) {
410:                applicationEventPublisher
411:                        .publishEvent(new JaasAuthenticationSuccessEvent(token));
412:            }
413:
414:            /**
415:             * Set the AuthorityGranters that should be consulted for role names to be granted to the Authentication.
416:             *
417:             * @param authorityGranters AuthorityGranter array
418:             *
419:             * @see JaasAuthenticationProvider
420:             */
421:            public void setAuthorityGranters(
422:                    AuthorityGranter[] authorityGranters) {
423:                this .authorityGranters = authorityGranters;
424:            }
425:
426:            /**
427:             * Set the JAASAuthentcationCallbackHandler array to handle callback objects generated by the
428:             * LoginContext.login method.
429:             *
430:             * @param callbackHandlers Array of JAASAuthenticationCallbackHandlers
431:             */
432:            public void setCallbackHandlers(
433:                    JaasAuthenticationCallbackHandler[] callbackHandlers) {
434:                this .callbackHandlers = callbackHandlers;
435:            }
436:
437:            /**
438:             * Set the JAAS login configuration file.
439:             *
440:             * @param loginConfig <a
441:             *        href="http://www.springframework.org/docs/api/org/springframework/core/io/Resource.html">Spring
442:             *        Resource</a>
443:             *
444:             * @see <a href="http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASRefGuide.html">JAAS Reference</a>
445:             */
446:            public void setLoginConfig(Resource loginConfig) {
447:                this .loginConfig = loginConfig;
448:            }
449:
450:            /**
451:             * Set the loginContextName, this name is used as the index to the configuration specified in the
452:             * loginConfig property.
453:             *
454:             * @param loginContextName
455:             */
456:            public void setLoginContextName(String loginContextName) {
457:                this .loginContextName = loginContextName;
458:            }
459:
460:            public void setLoginExceptionResolver(
461:                    LoginExceptionResolver loginExceptionResolver) {
462:                this .loginExceptionResolver = loginExceptionResolver;
463:            }
464:
465:            public boolean supports(Class aClass) {
466:                return UsernamePasswordAuthenticationToken.class
467:                        .isAssignableFrom(aClass);
468:            }
469:
470:            public void setApplicationEventPublisher(
471:                    ApplicationEventPublisher applicationEventPublisher) {
472:                this .applicationEventPublisher = applicationEventPublisher;
473:            }
474:
475:            protected ApplicationEventPublisher getApplicationEventPublisher() {
476:                return applicationEventPublisher;
477:            }
478:
479:            //~ Inner Classes ==================================================================================================
480:
481:            /**
482:             * Wrapper class for JAASAuthenticationCallbackHandlers
483:             */
484:            private class InternalCallbackHandler implements  CallbackHandler {
485:                private Authentication authentication;
486:
487:                public InternalCallbackHandler(Authentication authentication) {
488:                    this .authentication = authentication;
489:                }
490:
491:                public void handle(Callback[] callbacks) throws IOException,
492:                        UnsupportedCallbackException {
493:                    for (int i = 0; i < callbackHandlers.length; i++) {
494:                        JaasAuthenticationCallbackHandler handler = callbackHandlers[i];
495:
496:                        for (int j = 0; j < callbacks.length; j++) {
497:                            Callback callback = callbacks[j];
498:
499:                            handler.handle(callback, authentication);
500:                        }
501:                    }
502:                }
503:            }
504:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.