Source Code Cross Referenced for JaasSecurityManager.java in  » EJB-Server-JBoss-4.2.1 » security » org » jboss » security » plugins » 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 » EJB Server JBoss 4.2.1 » security » org.jboss.security.plugins 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * JBoss, Home of Professional Open Source.
003:         * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004:         * as indicated by the @author tags. See the copyright.txt file in the
005:         * distribution for a full listing of individual contributors.
006:         *
007:         * This is free software; you can redistribute it and/or modify it
008:         * under the terms of the GNU Lesser General Public License as
009:         * published by the Free Software Foundation; either version 2.1 of
010:         * the License, or (at your option) any later version.
011:         *
012:         * This software is distributed in the hope that it will be useful,
013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015:         * Lesser General Public License for more details.
016:         *
017:         * You should have received a copy of the GNU Lesser General Public
018:         * License along with this software; if not, write to the Free
019:         * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020:         * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021:         */
022:        package org.jboss.security.plugins;
023:
024:        import java.lang.reflect.Method;
025:        import java.lang.reflect.UndeclaredThrowableException;
026:        import java.security.Principal;
027:        import java.security.acl.Group;
028:        import java.util.Arrays;
029:        import java.util.Enumeration;
030:        import java.util.HashSet;
031:        import java.util.Iterator;
032:        import java.util.Set;
033:        import javax.security.auth.Subject;
034:        import javax.security.auth.callback.CallbackHandler;
035:        import javax.security.auth.login.LoginContext;
036:        import javax.security.auth.login.LoginException;
037:
038:        import org.jboss.logging.Logger;
039:        import org.jboss.security.AnybodyPrincipal;
040:        import org.jboss.security.NobodyPrincipal;
041:        import org.jboss.security.RealmMapping;
042:        import org.jboss.security.SecurityAssociation;
043:        import org.jboss.security.SecurityConstants;
044:        import org.jboss.security.SubjectSecurityManager;
045:        import org.jboss.security.auth.callback.SecurityAssociationHandler;
046:        import org.jboss.system.ServiceMBeanSupport;
047:        import org.jboss.util.CachePolicy;
048:        import org.jboss.util.TimedCachePolicy;
049:
050:        /** The JaasSecurityManager is responsible both for authenticating credentials
051:         associated with principals and for role mapping. This implementation relies
052:         on the JAAS LoginContext/LoginModules associated with the security
053:         domain name associated with the class for authentication,
054:         and the context JAAS Subject object for role mapping.
055:        
056:         @see #isValid(Principal, Object, Subject)
057:         @see #getPrincipal(Principal)
058:         @see #doesUserHaveRole(Principal, Set)
059:        
060:         @author <a href="on@ibis.odessa.ua">Oleg Nitz</a>
061:         @author Scott.Stark@jboss.org
062:         @version $Revision: 62863 $
063:         */
064:        public class JaasSecurityManager extends ServiceMBeanSupport implements 
065:                SubjectSecurityManager, RealmMapping {
066:            /** The authentication cache object.
067:             */
068:            public static class DomainInfo implements 
069:                    TimedCachePolicy.TimedEntry {
070:                private static Logger log = Logger.getLogger(DomainInfo.class);
071:                private static boolean trace = log.isTraceEnabled();
072:                private LoginContext loginCtx;
073:                private Subject subject;
074:                private Object credential;
075:                private Principal callerPrincipal;
076:                private long expirationTime;
077:                /** Is there an active authentication in process */
078:                private boolean needsDestroy;
079:                /** The number of users sharing this DomainInfo */
080:                private int activeUsers;
081:
082:                /**
083:                 Create a cache entry with the given lifetime in seconds. Since this comes
084:                 from the TimedCachePolicy, its expected to be <= Integer.MAX_VALUE.
085:                 
086:                 @param lifetime - lifetime in seconds. A lifetime <= 0 means no caching
087:                   with the exception of -1 which indicates that the cache entry never
088:                   expires.
089:                 */
090:                public DomainInfo(long lifetime) {
091:                    expirationTime = lifetime;
092:                    if (expirationTime != -1)
093:                        expirationTime *= 1000;
094:                }
095:
096:                synchronized int acquire() {
097:                    return activeUsers++;
098:                }
099:
100:                synchronized int release() {
101:                    int users = activeUsers--;
102:                    if (needsDestroy == true && users == 0) {
103:                        if (trace)
104:                            log.trace("needsDestroy is true, doing logout");
105:                        logout();
106:                    }
107:                    return users;
108:                }
109:
110:                synchronized void logout() {
111:                    if (trace)
112:                        log.trace("logout, subject=" + subject + ", this="
113:                                + this );
114:                    try {
115:                        if (loginCtx != null)
116:                            loginCtx.logout();
117:                    } catch (Throwable e) {
118:                        if (trace)
119:                            log.trace("Cache entry logout failed", e);
120:                    }
121:                }
122:
123:                public void init(long now) {
124:                    expirationTime += now;
125:                }
126:
127:                public boolean isCurrent(long now) {
128:                    boolean isCurrent = expirationTime == -1;
129:                    if (isCurrent == false)
130:                        isCurrent = expirationTime > now;
131:                    return isCurrent;
132:                }
133:
134:                public boolean refresh() {
135:                    return false;
136:                }
137:
138:                /**
139:                 * This 
140:                 */
141:                public void destroy() {
142:                    if (trace) {
143:                        log.trace("destroy, subject=" + subject + ", this="
144:                                + this  + ", activeUsers=" + activeUsers);
145:                    }
146:
147:                    synchronized (this ) {
148:                        if (activeUsers == 0)
149:                            logout();
150:                        else {
151:                            if (trace)
152:                                log.trace("destroy saw activeUsers="
153:                                        + activeUsers);
154:                            needsDestroy = true;
155:                        }
156:                    }
157:                }
158:
159:                public Object getValue() {
160:                    return this ;
161:                }
162:
163:                public String toString() {
164:                    StringBuffer tmp = new StringBuffer(super .toString());
165:                    tmp.append('[');
166:                    tmp.append(SubjectActions.toString(subject));
167:                    tmp.append(",credential.class=");
168:                    if (credential != null) {
169:                        Class c = credential.getClass();
170:                        tmp.append(c.getName());
171:                        tmp.append('@');
172:                        tmp.append(System.identityHashCode(c));
173:                    } else {
174:                        tmp.append("null");
175:                    }
176:                    tmp.append(",expirationTime=");
177:                    tmp.append(expirationTime);
178:                    tmp.append(']');
179:
180:                    return tmp.toString();
181:                }
182:            }
183:
184:            /** The name of the domain this instance is securing. It is used as
185:             the appName into the SecurityPolicy.
186:             */
187:            private String securityDomain;
188:            /** A cache of DomainInfo objects keyd by Principal. This is now
189:             always set externally by our security manager service.
190:             */
191:            private CachePolicy domainCache;
192:            /** The JAAS callback handler to use in defaultLogin */
193:            private CallbackHandler handler;
194:            /** The setSecurityInfo(Principal, Object) method of the handler obj */
195:            private Method setSecurityInfo;
196:            /** The flag to indicate that the Subject sets need to be deep copied*/
197:            private boolean deepCopySubjectOption = false;
198:
199:            /** The log4j category for the security manager domain
200:             */
201:            protected Logger log;
202:            protected boolean trace;
203:
204:            /** Creates a default JaasSecurityManager for default securityDomain.
205:             */
206:            public JaasSecurityManager() {
207:                this (SecurityConstants.DEFAULT_APPLICATION_POLICY,
208:                        new SecurityAssociationHandler());
209:            }
210:
211:            /** Creates a JaasSecurityManager for with a securityDomain
212:             name of that given by the 'securityDomain' argument.
213:             @param securityDomain the name of the security domain
214:             @param handler the JAAS callback handler instance to use
215:             @exception UndeclaredThrowableException thrown if handler does not
216:               implement a setSecurityInfo(Princpal, Object) method
217:             */
218:            public JaasSecurityManager(String securityDomain,
219:                    CallbackHandler handler) {
220:                this .securityDomain = securityDomain;
221:                this .handler = handler;
222:                String categoryName = getClass().getName() + '.'
223:                        + securityDomain;
224:                this .log = Logger.getLogger(categoryName);
225:                this .trace = log.isTraceEnabled();
226:
227:                // Get the setSecurityInfo(Principal principal, Object credential) method
228:                Class[] sig = { Principal.class, Object.class };
229:                try {
230:                    setSecurityInfo = handler.getClass().getMethod(
231:                            "setSecurityInfo", sig);
232:                } catch (Exception e) {
233:                    String msg = "Failed to find setSecurityInfo(Princpal, Object) method in handler";
234:                    throw new UndeclaredThrowableException(e, msg);
235:                }
236:                log.debug("CallbackHandler: " + handler);
237:            }
238:
239:            /** The domainCache is typically a shared object that is populated
240:             by the login code(LoginModule, etc.) and read by this class in the
241:             isValid() method.
242:             @see #isValid(Principal, Object, Subject)
243:             */
244:            public void setCachePolicy(CachePolicy domainCache) {
245:                this .domainCache = domainCache;
246:                log.debug("CachePolicy set to: " + domainCache);
247:            }
248:
249:            /**
250:             * Flag to specify if deep copy of subject sets needs to be 
251:             * enabled
252:             * 
253:             * @param flag
254:             */
255:            public void setDeepCopySubjectOption(Boolean flag) {
256:                log.debug("setDeepCopySubjectOption=" + flag);
257:                this .deepCopySubjectOption = (flag == Boolean.TRUE);
258:            }
259:
260:            /** Not really used anymore as the security manager service manages the
261:             security domain authentication caches.
262:             */
263:            public void flushCache() {
264:                if (domainCache != null)
265:                    domainCache.flush();
266:            }
267:
268:            /** Get the name of the security domain associated with this security mgr.
269:             @return Name of the security manager security domain.
270:             */
271:            public String getSecurityDomain() {
272:                return securityDomain;
273:            }
274:
275:            /** Get the currently authenticated Subject. This is a thread local
276:             property shared across all JaasSecurityManager instances.
277:             @return The Subject authenticated in the current thread if one
278:             exists, null otherwise.
279:             */
280:            public Subject getActiveSubject() {
281:                /* This does not use SubjectActions.getActiveSubject since the caller
282:                   must have the correct permissions to access the
283:                   SecurityAssociation.getSubject method.
284:                 */
285:                return SecurityAssociation.getSubject();
286:            }
287:
288:            /** Validate that the given credential is correct for principal. This
289:             returns the value from invoking isValid(principal, credential, null).
290:             @param principal - the security domain principal attempting access
291:             @param credential - the proof of identity offered by the principal
292:             @return true if the principal was authenticated, false otherwise.
293:             */
294:            public boolean isValid(Principal principal, Object credential) {
295:                return isValid(principal, credential, null);
296:            }
297:
298:            /** Validate that the given credential is correct for principal. This first
299:             will check the current CachePolicy object if one exists to see if the
300:             user's cached credentials match the given credential. If there is no
301:             credential cache or the cache information is invalid or does not match,
302:             the user is authenticated against the JAAS login modules configured for
303:             the security domain.
304:             @param principal - the security domain principal attempting access
305:             @param credential  the proof of identity offered by the principal
306:             @param activeSubject - if not null, a Subject that will be populated with
307:               the state of the authenticated Subject.
308:             @return true if the principal was authenticated, false otherwise.
309:             */
310:            public boolean isValid(Principal principal, Object credential,
311:                    Subject activeSubject) {
312:                // Check the cache first
313:                DomainInfo cacheInfo = getCacheInfo(principal, true);
314:                if (trace)
315:                    log.trace("Begin isValid, principal:" + principal
316:                            + ", cache info: " + cacheInfo);
317:
318:                boolean isValid = false;
319:                if (cacheInfo != null) {
320:                    isValid = validateCache(cacheInfo, credential,
321:                            activeSubject);
322:                    if (cacheInfo != null)
323:                        cacheInfo.release();
324:                }
325:                if (isValid == false)
326:                    isValid = authenticate(principal, credential, activeSubject);
327:                if (trace)
328:                    log.trace("End isValid, " + isValid);
329:                return isValid;
330:            }
331:
332:            /** Map the argument principal from the deployment environment principal
333:             to the developer environment. This is called by the EJB context
334:             getCallerPrincipal() to return the Principal as described by
335:             the EJB developer domain.
336:             @return a Principal object that is valid in the deployment environment
337:             if one exists. If no Subject exists or the Subject has no principals
338:             then the argument principal is returned.
339:             */
340:            public Principal getPrincipal(Principal principal) {
341:                if (domainCache == null)
342:                    return principal;
343:                Principal result = principal;
344:                // Get the CallerPrincipal group member
345:                synchronized (domainCache) {
346:                    DomainInfo info = getCacheInfo(principal, false);
347:                    if (trace)
348:                        log.trace("getPrincipal, cache info: " + info);
349:                    if (info != null) {
350:                        result = info.callerPrincipal;
351:                        // If the mapping did not have a callerPrincipal just use principal
352:                        if (result == null)
353:                            result = principal;
354:                        info.release();
355:                    }
356:                }
357:
358:                return result;
359:            }
360:
361:            /** Does the current Subject have a role(a Principal) that equates to one
362:             of the role names. This method obtains the Group named 'Roles' from
363:             the principal set of the currently authenticated Subject as determined
364:             by the SecurityAssociation.getSubject() method and then creates a
365:             SimplePrincipal for each name in roleNames. If the role is a member of the
366:             Roles group, then the user has the role. This requires that the caller
367:             establish the correct SecurityAssociation subject prior to calling this
368:             method. In the past this was done as a side-effect of an isValid() call,
369:             but this is no longer the case.
370:
371:             @param principal - ignored. The current authenticated Subject determines
372:             the active user and assigned user roles.
373:             @param rolePrincipals - a Set of Principals for the roles to check.
374:             
375:             @see java.security.acl.Group;
376:             @see Subject#getPrincipals()
377:             */
378:            public boolean doesUserHaveRole(Principal principal,
379:                    Set rolePrincipals) {
380:                boolean hasRole = false;
381:                // Check that the caller is authenticated to the current thread
382:                Subject subject = SubjectActions.getActiveSubject();
383:                if (subject != null) {
384:                    // Check the caller's roles
385:                    if (trace)
386:                        log.trace("doesUserHaveRole(Set), subject: " + subject);
387:
388:                    Group roles = getSubjectRoles(subject);
389:                    if (trace)
390:                        log.trace("roles=" + roles);
391:                    if (roles != null) {
392:                        Iterator iter = rolePrincipals.iterator();
393:                        while (hasRole == false && iter.hasNext()) {
394:                            Principal role = (Principal) iter.next();
395:                            hasRole = doesRoleGroupHaveRole(role, roles);
396:                            if (trace)
397:                                log.trace("hasRole(" + role + ")=" + hasRole);
398:                        }
399:                    }
400:                    if (trace)
401:                        log.trace("hasRole=" + hasRole);
402:                }
403:                return hasRole;
404:            }
405:
406:            /** Does the current Subject have a role(a Principal) that equates to one
407:             of the role names.
408:
409:             @see #doesUserHaveRole(Principal, Set)
410:
411:             @param principal - ignored. The current authenticated Subject determines
412:             the active user and assigned user roles.
413:             @param role - the application domain role that the principal is to be
414:               validated against.
415:             @return true if the active principal has the role, false otherwise.
416:             */
417:            public boolean doesUserHaveRole(Principal principal, Principal role) {
418:                boolean hasRole = false;
419:                // Check that the caller is authenticated to the current thread
420:                Subject subject = SubjectActions.getActiveSubject();
421:                if (subject != null) {
422:                    // Check the caller's roles
423:                    if (trace)
424:                        log.trace("doesUserHaveRole(Principal), subject: "
425:                                + subject);
426:
427:                    Group roles = getSubjectRoles(subject);
428:                    if (roles != null) {
429:                        hasRole = doesRoleGroupHaveRole(role, roles);
430:                    }
431:                }
432:                return hasRole;
433:            }
434:
435:            /** Return the set of domain roles the current active Subject 'Roles' group
436:               found in the subject Principals set.
437:
438:             @param principal - ignored. The current authenticated Subject determines
439:             the active user and assigned user roles.
440:             @return The Set<Principal> for the application domain roles that the
441:             principal has been assigned.
442:             */
443:            public Set getUserRoles(Principal principal) {
444:                HashSet userRoles = null;
445:                // Check that the caller is authenticated to the current thread
446:                Subject subject = SubjectActions.getActiveSubject();
447:                if (subject != null) {
448:                    // Copy the caller's roles
449:                    if (trace)
450:                        log.trace("getUserRoles, subject: " + subject);
451:
452:                    Group roles = getSubjectRoles(subject);
453:                    if (roles != null) {
454:                        userRoles = new HashSet();
455:                        Enumeration members = roles.members();
456:                        while (members.hasMoreElements()) {
457:                            Principal role = (Principal) members.nextElement();
458:                            userRoles.add(role);
459:                        }
460:                    }
461:                }
462:                return userRoles;
463:            }
464:
465:            /** Check that the indicated application domain role is a member of the
466:             user's assigned roles. This handles the special AnybodyPrincipal and
467:             NobodyPrincipal independent of the Group implementation.
468:
469:             @param role , the application domain role required for access
470:             @param userRoles , the set of roles assigned to the user
471:             @return true if role is in userRoles or an AnybodyPrincipal instance, false
472:             if role is a NobodyPrincipal or no a member of userRoles
473:             */
474:            protected boolean doesRoleGroupHaveRole(Principal role,
475:                    Group userRoles) {
476:                // First check that role is not a NobodyPrincipal
477:                if (role instanceof  NobodyPrincipal)
478:                    return false;
479:
480:                // Check for inclusion in the user's role set
481:                boolean isMember = userRoles.isMember(role);
482:                if (isMember == false) { // Check the AnybodyPrincipal special cases
483:                    isMember = (role instanceof  AnybodyPrincipal);
484:                }
485:
486:                return isMember;
487:            }
488:
489:            /** Currently this simply calls defaultLogin() to do a JAAS login using the
490:             security domain name as the login module configuration name.
491:             
492:             * @param principal - the user id to authenticate
493:             * @param credential - an opaque credential.
494:             * @return false on failure, true on success.
495:             */
496:            private boolean authenticate(Principal principal,
497:                    Object credential, Subject theSubject) {
498:                Subject subject = null;
499:                boolean authenticated = false;
500:                LoginException authException = null;
501:
502:                try {
503:                    // Validate the principal using the login configuration for this domain
504:                    LoginContext lc = defaultLogin(principal, credential);
505:                    subject = lc.getSubject();
506:
507:                    // Set the current subject if login was successful
508:                    if (subject != null) {
509:                        // Copy the current subject into theSubject
510:                        if (theSubject != null) {
511:                            SubjectActions.copySubject(subject, theSubject,
512:                                    false, this .deepCopySubjectOption);
513:                        } else {
514:                            theSubject = subject;
515:                        }
516:
517:                        authenticated = true;
518:                        // Build the Subject based DomainInfo cache value
519:                        updateCache(lc, subject, principal, credential);
520:                    }
521:                } catch (LoginException e) {
522:                    // Don't log anonymous user failures unless trace level logging is on
523:                    if (principal != null && principal.getName() != null
524:                            || trace)
525:                        log.trace("Login failure", e);
526:                    authException = e;
527:                }
528:                // Set the security association thread context info exception
529:                SubjectActions.setContextInfo("org.jboss.security.exception",
530:                        authException);
531:
532:                return authenticated;
533:            }
534:
535:            /** Pass the security info to the login modules configured for
536:             this security domain using our SecurityAssociationHandler.
537:             @return The authenticated Subject if successful.
538:             @exception LoginException throw if login fails for any reason.
539:             */
540:            private LoginContext defaultLogin(Principal principal,
541:                    Object credential) throws LoginException {
542:                /* We use our internal CallbackHandler to provide the security info. A
543:                copy must be made to ensure there is a unique handler per active
544:                login since there can be multiple active logins.
545:                 */
546:                Object[] securityInfo = { principal, credential };
547:                CallbackHandler theHandler = null;
548:                try {
549:                    theHandler = (CallbackHandler) handler.getClass()
550:                            .newInstance();
551:                    setSecurityInfo.invoke(theHandler, securityInfo);
552:                } catch (Throwable e) {
553:                    if (trace)
554:                        log.trace(
555:                                "Failed to create/setSecurityInfo on handler",
556:                                e);
557:                    LoginException le = new LoginException(
558:                            "Failed to setSecurityInfo on handler");
559:                    le.initCause(e);
560:                    throw le;
561:                }
562:                Subject subject = new Subject();
563:                LoginContext lc = null;
564:                if (trace)
565:                    log.trace("defaultLogin, principal=" + principal);
566:                lc = SubjectActions.createLoginContext(securityDomain, subject,
567:                        theHandler);
568:                lc.login();
569:                if (trace)
570:                    log.trace("defaultLogin, lc=" + lc + ", subject="
571:                            + SubjectActions.toString(subject));
572:                return lc;
573:            }
574:
575:            /** Validate the cache credential value against the provided credential
576:             */
577:            private boolean validateCache(DomainInfo info, Object credential,
578:                    Subject theSubject) {
579:                if (trace) {
580:                    StringBuffer tmp = new StringBuffer(
581:                            "Begin validateCache, info=");
582:                    tmp.append(info.toString());
583:                    tmp.append(";credential.class=");
584:                    if (credential != null) {
585:                        Class c = credential.getClass();
586:                        tmp.append(c.getName());
587:                        tmp.append('@');
588:                        tmp.append(System.identityHashCode(c));
589:                    } else {
590:                        tmp.append("null");
591:                    }
592:                    log.trace(tmp.toString());
593:                }
594:
595:                Object subjectCredential = info.credential;
596:                boolean isValid = false;
597:                // Check for a null credential as can be the case for an anonymous user
598:                if (credential == null || subjectCredential == null) {
599:                    // Both credentials must be null
600:                    isValid = (credential == null)
601:                            && (subjectCredential == null);
602:                }
603:                // See if the credential is assignable to the cache value
604:                else if (subjectCredential.getClass().isAssignableFrom(
605:                        credential.getClass())) {
606:                    /* Validate the credential by trying Comparable, char[], byte[],
607:                     Object[], and finally Object.equals()
608:                     */
609:                    if (subjectCredential instanceof  Comparable) {
610:                        Comparable c = (Comparable) subjectCredential;
611:                        isValid = c.compareTo(credential) == 0;
612:                    } else if (subjectCredential instanceof  char[]) {
613:                        char[] a1 = (char[]) subjectCredential;
614:                        char[] a2 = (char[]) credential;
615:                        isValid = Arrays.equals(a1, a2);
616:                    } else if (subjectCredential instanceof  byte[]) {
617:                        byte[] a1 = (byte[]) subjectCredential;
618:                        byte[] a2 = (byte[]) credential;
619:                        isValid = Arrays.equals(a1, a2);
620:                    } else if (subjectCredential.getClass().isArray()) {
621:                        Object[] a1 = (Object[]) subjectCredential;
622:                        Object[] a2 = (Object[]) credential;
623:                        isValid = Arrays.equals(a1, a2);
624:                    } else {
625:                        isValid = subjectCredential.equals(credential);
626:                    }
627:                } else if (subjectCredential instanceof  char[]
628:                        && credential instanceof  String) {
629:                    char[] a1 = (char[]) subjectCredential;
630:                    char[] a2 = ((String) credential).toCharArray();
631:                    isValid = Arrays.equals(a1, a2);
632:                } else if (subjectCredential instanceof  String
633:                        && credential instanceof  char[]) {
634:                    char[] a1 = ((String) subjectCredential).toCharArray();
635:                    char[] a2 = (char[]) credential;
636:                    isValid = Arrays.equals(a1, a2);
637:                }
638:
639:                // If the credentials match, set the thread's active Subject
640:                if (isValid) {
641:                    // Copy the current subject into theSubject
642:                    if (theSubject != null) {
643:                        SubjectActions.copySubject(info.subject, theSubject,
644:                                false, this .deepCopySubjectOption);
645:                    }
646:                }
647:                if (trace)
648:                    log.trace("End validateCache, isValid=" + isValid);
649:
650:                return isValid;
651:            }
652:
653:            /** An accessor method that synchronizes access on the domainCache
654:             to avoid a race condition that can occur when the cache entry expires
655:             in the presence of multi-threaded access. The allowRefresh flag should
656:             be true for authentication accesses and false for other accesses.
657:             Previously the other accesses included authorization and caller principal
658:             mapping. Now the only use of the 
659:
660:             @param principal - the caller identity whose cached credentials are to
661:             be accessed.
662:             @param allowRefresh - a flag indicating if the cache access should flush
663:             any expired entries.
664:             */
665:            private DomainInfo getCacheInfo(Principal principal,
666:                    boolean allowRefresh) {
667:                if (domainCache == null)
668:                    return null;
669:
670:                DomainInfo cacheInfo = null;
671:                synchronized (domainCache) {
672:                    if (allowRefresh == true)
673:                        cacheInfo = (DomainInfo) domainCache.get(principal);
674:                    else
675:                        cacheInfo = (DomainInfo) domainCache.peek(principal);
676:                    if (cacheInfo != null)
677:                        cacheInfo.acquire();
678:                }
679:                return cacheInfo;
680:            }
681:
682:            private Subject updateCache(LoginContext lc, Subject subject,
683:                    Principal principal, Object credential) {
684:                // If we don't have a cache there is nothing to update
685:                if (domainCache == null)
686:                    return subject;
687:
688:                long lifetime = 0;
689:                if (domainCache instanceof  TimedCachePolicy) {
690:                    TimedCachePolicy cache = (TimedCachePolicy) domainCache;
691:                    lifetime = cache.getDefaultLifetime();
692:                }
693:                DomainInfo info = new DomainInfo(lifetime);
694:                info.loginCtx = lc;
695:                info.subject = new Subject();
696:                SubjectActions.copySubject(subject, info.subject, true,
697:                        this .deepCopySubjectOption);
698:                info.credential = credential;
699:
700:                if (trace) {
701:                    log.trace("updateCache, inputSubject="
702:                            + SubjectActions.toString(subject)
703:                            + ", cacheSubject="
704:                            + SubjectActions.toString(info.subject));
705:                }
706:
707:                /* Get the Subject callerPrincipal by looking for a Group called
708:                   'CallerPrincipal'
709:                 */
710:                Set subjectGroups = subject.getPrincipals(Group.class);
711:                Iterator iter = subjectGroups.iterator();
712:                while (iter.hasNext()) {
713:                    Group grp = (Group) iter.next();
714:                    String name = grp.getName();
715:                    if (name.equals("CallerPrincipal")) {
716:                        Enumeration members = grp.members();
717:                        if (members.hasMoreElements())
718:                            info.callerPrincipal = (Principal) members
719:                                    .nextElement();
720:                    }
721:                }
722:
723:                /* Handle null principals with no callerPrincipal. This is an indication
724:                   of an user that has not provided any authentication info, but
725:                   has been authenticated by the domain login module stack. Here we look
726:                   for the first non-Group Principal and use that.
727:                 */
728:                if (principal == null && info.callerPrincipal == null) {
729:                    Set subjectPrincipals = subject
730:                            .getPrincipals(Principal.class);
731:                    iter = subjectPrincipals.iterator();
732:                    while (iter.hasNext()) {
733:                        Principal p = (Principal) iter.next();
734:                        if ((p instanceof  Group) == false)
735:                            info.callerPrincipal = p;
736:                    }
737:                }
738:
739:                /* If the user already exists another login is active. Currently
740:                   only one is allowed so remove the old and insert the new. Synchronize
741:                   on the domainCache to ensure the removal and addition are an atomic
742:                   operation so that getCacheInfo cannot see stale data.
743:                 */
744:                synchronized (domainCache) {
745:                    if (domainCache.peek(principal) != null)
746:                        domainCache.remove(principal);
747:                    domainCache.insert(principal, info);
748:                    if (trace)
749:                        log.trace("Inserted cache info: " + info);
750:                }
751:                return info.subject;
752:            }
753:
754:            /**
755:             * Get the Subject roles by looking for a Group called 'Roles'
756:             * @param theSubject - the Subject to search for roles
757:             * @return the Group contain the subject roles if found, null otherwise
758:             */
759:            private Group getSubjectRoles(Subject theSubject) {
760:                Set subjectGroups = theSubject.getPrincipals(Group.class);
761:                Iterator iter = subjectGroups.iterator();
762:                Group roles = null;
763:                while (iter.hasNext()) {
764:                    Group grp = (Group) iter.next();
765:                    String name = grp.getName();
766:                    if (name.equals("Roles"))
767:                        roles = grp;
768:                }
769:                return roles;
770:            }
771:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.