User: starksm Date: 01/11/09 02:25:55 Modified: src/main/org/jboss/security/plugins Tag: Branch_2_4 JaasSecurityManagerServiceMBean.java JaasSecurityManagerService.java Log: Add support for authentication caches per domain and setting the default timed cache timeout and resolution Revision Changes Path No revision No revision 1.1.2.3 +53 -25 jbosssx/src/main/org/jboss/security/plugins/JaasSecurityManagerServiceMBean.java Index: JaasSecurityManagerServiceMBean.java =================================================================== RCS file: /cvsroot/jboss/jbosssx/src/main/org/jboss/security/plugins/JaasSecurityManagerServiceMBean.java,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -r1.1.2.2 -r1.1.2.3 --- JaasSecurityManagerServiceMBean.java 2001/09/26 06:36:35 1.1.2.2 +++ JaasSecurityManagerServiceMBean.java 2001/11/09 10:25:55 1.1.2.3 @@ -10,40 +10,68 @@ /** The interface for the JaasSecurityManagerService mbean. @author [EMAIL PROTECTED] - @version $Revision: 1.1.2.2 $ -*/ + @version $Revision: 1.1.2.3 $ + */ public interface JaasSecurityManagerServiceMBean - extends org.jboss.util.ServiceMBean +extends org.jboss.util.ServiceMBean { // Constants ----------------------------------------------------- public static final String OBJECT_NAME = "Security:name=JaasSecurityManager"; - + // Public -------------------------------------------------------- /** Get the name of the class that provides the security manager implementation. */ - public String getSecurityManagerClassName(); + public String getSecurityManagerClassName(); /** Set the name of the class that provides the security manager implementation. + @exception ClassNotFoundException, thrown if the className cannot be found + using the thread context class loader. + @exception ClassCastException, thrown if the className does not implement the + org.jboss.security.AuthenticationManager interface. */ - public void setSecurityManagerClassName(String className) throws ClassNotFoundException; - /** Get the name of the class that provides the SecurityProxyFactory implementation. - */ - public String getSecurityProxyFactoryClassName(); - /** Set the name of the class that provides the SecurityProxyFactory implementation. - */ - public void setSecurityProxyFactoryClassName(String className) throws ClassNotFoundException; + public void setSecurityManagerClassName(String className) + throws ClassNotFoundException, ClassCastException; + /** Get the name of the class that provides the SecurityProxyFactory implementation. + */ + public String getSecurityProxyFactoryClassName(); + /** Set the name of the class that provides the SecurityProxyFactory implementation. + */ + public void setSecurityProxyFactoryClassName(String className) + throws ClassNotFoundException; /** Get the jndi name under which the authentication CachePolicy implenentation - is found + is found + */ + public String getAuthenticationCacheJndiName(); + /** Set the location of the security credential cache policy. This is first treated + as a ObjectFactory location that is capable of returning CachePolicy instances + on a per security domain basis by appending a '/security-domain-name' string + to this name when looking up the CachePolicy for a domain. If this fails then + the location is treated as a single CachePolicy for all security domains. + @param jndiName, the name to the ObjectFactory or CachePolicy binding. + */ + public void setAuthenticationCacheJndiName(String jndiName); + /** flush the cache policy for the indicated security domain if the security manager + instance supports a flushCache() method. + */ + /** Get the default timed cache policy timeout. + @return the default cache timeout in seconds. + */ + public int getDefaultCacheTimeout(); + /** Set the default timed cache policy timeout. This has no affect if the + AuthenticationCacheJndiName has been changed from the default value. + @param timeoutInSecs, the cache timeout in seconds. + */ + public void setDefaultCacheTimeout(int timeoutInSecs); + /** Get the default timed cache policy resolution. + */ + public int getDefaultCacheResolution(); + /** Set the default timed cache policy resolution. This has no affect if the + AuthenticationCacheJndiName has been changed from the default value. + @param resInSecs, resolution of timeouts in seconds. + */ + public void setDefaultCacheResolution(int resInSecs); + + public void flushAuthenticationCache(String securityDomain); + /** Register a SecurityDomain implmentation */ - public String getAuthenticationCacheJndiName(); - /** Set the jndi name under which the authentication CachePolicy implenentation - is found - */ - public void setAuthenticationCacheJndiName(String jndiName); - /** flush the cache policy for the indicated security domain if the security manager - instance supports a flushCache() method. - */ - public void flushAuthenticationCache(String securityDomain); - /** Register a SecurityDomain implmentation - */ - public void registerSecurityDomain(String securityDomain, SecurityDomain instance); + public void registerSecurityDomain(String securityDomain, SecurityDomain instance); } 1.2.2.6 +166 -66 jbosssx/src/main/org/jboss/security/plugins/JaasSecurityManagerService.java Index: JaasSecurityManagerService.java =================================================================== RCS file: /cvsroot/jboss/jbosssx/src/main/org/jboss/security/plugins/JaasSecurityManagerService.java,v retrieving revision 1.2.2.5 retrieving revision 1.2.2.6 diff -u -r1.2.2.5 -r1.2.2.6 --- JaasSecurityManagerService.java 2001/09/26 06:36:35 1.2.2.5 +++ JaasSecurityManagerService.java 2001/11/09 10:25:55 1.2.2.6 @@ -40,12 +40,13 @@ import org.apache.log4j.Category; import org.jboss.logging.log4j.JBossCategory; +import org.jboss.security.AuthenticationManager; import org.jboss.security.SecurityAssociation; import org.jboss.security.SecurityProxyFactory; import org.jboss.security.SecurityDomain; -import org.jboss.security.SubjectSecurityManager; import org.jboss.util.CachePolicy; import org.jboss.util.ServiceMBeanSupport; +import org.jboss.util.TimedCachePolicy; /** * This is a JMX service which manages JAAS based SecurityManagers. @@ -64,20 +65,28 @@ extends ServiceMBeanSupport implements JaasSecurityManagerServiceMBean { + private static final String SECURITY_MGR_PATH = "java:/jaas"; + private static final String DEFAULT_CACHE_POLICY_PATH = "java:/timedCacheFactory"; /** The log4j interface */ private static Category log; /** The class that provides the security manager implementation */ private static String securityMgrClassName = "org.jboss.security.plugins.JaasSecurityManager"; /** The loaded securityMgrClassName */ private static Class securityMgrClass; - /** The security credential cache policy, shared by all security mgrs */ - private static CachePolicy cachePolicy; - private static String cacheJndiName; + /** The location of the security credential cache policy. This is first treated + as a ObjectFactory location that is capable of returning CachePolicy instances + on a per security domain basis by appending a '/security-domain-name' string + to this name when looking up the CachePolicy for a domain. If this fails then + the location is treated as a single CachePolicy for all security domains. + */ + private static String cacheJndiName = DEFAULT_CACHE_POLICY_PATH; + private static int defaultCacheTimeout = 30*60; + private static int defaultCacheResolution = 60; /** The class that provides the SecurityProxyFactory implementation */ private static String securityProxyFactoryClassName = "org.jboss.security.SubjectSecurityProxyFactory"; private static Class securityProxyFactoryClass = org.jboss.security.SubjectSecurityProxyFactory.class; - - private static Hashtable jsmMap = new Hashtable(); + /** A mapping from security domain name to a SecurityDomainContext object */ + private static Hashtable securityDomainCtxMap = new Hashtable(); private static NameParser parser; private static MBeanServer server; @@ -103,11 +112,13 @@ return securityMgrClassName; } public void setSecurityManagerClassName(String className) - throws ClassNotFoundException + throws ClassNotFoundException, ClassCastException { securityMgrClassName = className; ClassLoader loader = Thread.currentThread().getContextClassLoader(); securityMgrClass = loader.loadClass(securityMgrClassName); + if( AuthenticationManager.class.isAssignableFrom(securityMgrClass) == false ) + throw new ClassCastException(securityMgrClass+" does not implement "+AuthenticationManager.class); } public String getSecurityProxyFactoryClassName() { @@ -132,26 +143,48 @@ { this.cacheJndiName = jndiName; } + /** Get the default timed cache policy timeout. + @return the default cache timeout in seconds. + */ + public int getDefaultCacheTimeout() + { + return defaultCacheTimeout; + } + /** Set the default timed cache policy timeout. This has no affect if the + AuthenticationCacheJndiName has been changed from the default value. + @param timeoutInSecs, the cache timeout in seconds. + */ + public void setDefaultCacheTimeout(int timeoutInSecs) + { + this.defaultCacheTimeout = timeoutInSecs; + } + /** Get the default timed cache policy resolution. + */ + public int getDefaultCacheResolution() + { + return defaultCacheResolution; + } + /** Set the default timed cache policy resolution. This has no affect if the + AuthenticationCacheJndiName has been changed from the default value. + @param resInSecs, resolution of timeouts in seconds. + */ + public void setDefaultCacheResolution(int resInSecs) + { + this.defaultCacheResolution = resInSecs; + } + /** flush the cache policy for the indicated security domain if the security manager * instance supports a flushCache() method. */ public void flushAuthenticationCache(String securityDomain) { - String jndiName = "java:/jaas/" + securityDomain; - try - { - InitialContext ic = new InitialContext(); - Object securityMgr = ic.lookup(jndiName); - Class clazz = securityMgr.getClass(); - Class[] argTypes = {}; - Method flush = clazz.getMethod("flushCache", argTypes); - Object[] args = {}; - flush.invoke(securityMgr, args); - } - catch(Exception e) - { - log.error("flushAuthenticationCache failed", e); - } + SecurityDomainContext securityDomainCtx = (SecurityDomainContext) securityDomainCtxMap.get(securityDomain); + if( securityDomainCtx != null ) + { + CachePolicy cache = securityDomainCtx.getAuthenticationCache(); + if( cache != null ) + cache.flush(); + } } public String getName() @@ -163,31 +196,32 @@ throws MalformedObjectNameException { JaasSecurityManagerService.server = server; - return new ObjectName(OBJECT_NAME); + return super.getObjectName(server, name); } protected void startService() throws Exception { InitialContext ic = new InitialContext(); - // Bind reference to SM subcontext in JNDI - // Uses JNDI federation to handle the "java:/jaas" context ourselves - RefAddr refAddr = new StringRefAddr("nns", "JSM"); - String factoryName = SecurityDomainObjectFactory.class.getName(); - Reference jsmsRef = new Reference("javax.naming.Context", refAddr, factoryName, null); Context ctx = new InitialContext(); - ctx.rebind("java:/jaas", jsmsRef); parser = ctx.getNameParser(""); - try - { - if( cacheJndiName != null ) - cachePolicy = (CachePolicy) ctx.lookup(cacheJndiName); - } - catch(NamingException e) - { - } - log.info("startService, cachePolicy="+cachePolicy); + /* Create a mapping from the java:/jaas context to a SecurityDomainObjectFactory + so that any lookup against java:/jaas/domain returns an instance of our + security manager class. + */ + RefAddr refAddr = new StringRefAddr("nns", "JSM"); + String factoryName = SecurityDomainObjectFactory.class.getName(); + Reference ref = new Reference("javax.naming.Context", refAddr, factoryName, null); + ctx.rebind(SECURITY_MGR_PATH, ref); + log.info("startService, securityMgrCtxPath="+SECURITY_MGR_PATH); + + refAddr = new StringRefAddr("nns", "JSMCachePolicy"); + factoryName = DefaultCacheObjectFactory.class.getName(); + ref = new Reference("javax.naming.Context", refAddr, factoryName, null); + ctx.rebind(DEFAULT_CACHE_POLICY_PATH, ref); + log.info("startService, cachePolicyCtxPath="+cacheJndiName); + // Bind the default SecurityProxyFactory instance under java:/SecurityProxyFactory SecurityProxyFactory proxyFactory = (SecurityProxyFactory) securityProxyFactoryClass.newInstance(); ctx.bind("java:/SecurityProxyFactory", proxyFactory); @@ -200,7 +234,7 @@ try { ic = new InitialContext(); - ic.unbind("java:/jaas"); + ic.unbind(SECURITY_MGR_PATH); } catch(CommunicationException e) { @@ -211,16 +245,51 @@ log.error("stopService", e); } } - + /** Register a SecurityDomain implmentation */ public void registerSecurityDomain(String securityDomain, SecurityDomain instance) { log.info("Added "+securityDomain+", "+instance+" to map"); - jsmMap.put(securityDomain, instance); + CachePolicy authCache = getCachePolicy(securityDomain); + SecurityDomainContext sdc = new SecurityDomainContext(instance, authCache); + securityDomainCtxMap.put(securityDomain, sdc); } - // ObjectFactory implementation ---------------------------------- + /** Lookup the authentication CachePolicy object for a security domain. This + method first treats the cacheJndiName as a ObjectFactory location that is + capable of returning CachePolicy instances on a per security domain basis + by appending a '/security-domain-name' string to the cacheJndiName when + looking up the CachePolicy for a domain. If this fails then the cacheJndiName + location is treated as a single CachePolicy for all security domains. + */ + private static CachePolicy getCachePolicy(String securityDomain) + { + CachePolicy authCache = null; + String domainCachePath = cacheJndiName + '/' + securityDomain; + try + { + InitialContext iniCtx = new InitialContext(); + authCache = (CachePolicy) iniCtx.lookup(domainCachePath); + } + catch(Exception e) + { + // Failed, treat the cacheJndiName name as a global CachePolicy binding + try + { + InitialContext iniCtx = new InitialContext(); + authCache = (CachePolicy) iniCtx.lookup(cacheJndiName); + } + catch(Exception e2) + { + log.warn("Failed to locate auth CachePolicy at: "+cacheJndiName + + " for securityDomain="+securityDomain); + } + } + return authCache; + } + + // java:/jaas context ObjectFactory implementation public static class SecurityDomainObjectFactory implements InvocationHandler, ObjectFactory { @@ -237,18 +306,21 @@ return ctx; } - private Object newSecurityMgr(String securityDomain) throws NamingException + private SecurityDomainContext newSecurityDomainCtx(String securityDomain) + throws NamingException { - Object securityMgr = null; + SecurityDomainContext sdc = null; try - { + { // Create instance of securityMgrClass Class[] parameterTypes = {String.class}; Constructor ctor = securityMgrClass.getConstructor(parameterTypes); Object[] args = {securityDomain}; ObjectName name = new ObjectName(server.getDefaultDomain(), "securityDomain", securityDomain); - securityMgr = ctor.newInstance(args); + AuthenticationManager securityMgr = (AuthenticationManager) ctor.newInstance(args); log.info("Created securityMgr="+securityMgr); + CachePolicy cachePolicy = getCachePolicy(securityDomain); + sdc = new SecurityDomainContext(securityMgr, cachePolicy); // See if the security mgr supports an externalized cache policy try { @@ -261,24 +333,26 @@ catch(Exception e2) { // No cache policy support, this is ok } - log.info("Added "+securityDomain+", "+securityMgr+" to map"); - jsmMap.put(securityDomain, securityMgr); } catch(Exception e2) { log.error("Failed to create sec mgr", e2); throw new NamingException("Failed to create sec mgr:"+e2.getMessage()); } - return securityMgr; + return sdc; } + /** This is the InvocationHandler callback for the Context interface that + was created by out getObjectInstance() method. We handle the java:/jaas/domain + level operations here. + */ public Object invoke(Object obj, Method method, Object[] args) throws Throwable { String methodName = method.getName(); if( methodName.equals("toString") == true ) - return "java:/jaas Context proxy"; + return SECURITY_MGR_PATH + " Context proxy"; if( methodName.equals("list") == true ) - return new DomainEnumeration(jsmMap.keys(), jsmMap); + return new DomainEnumeration(securityDomainCtxMap.keys(), securityDomainCtxMap); if( methodName.equals("lookup") == false ) throw new OperationNotSupportedException("Only lookup is supported, op="+method); @@ -289,22 +363,19 @@ else name = (Name)args[0]; securityDomain = name.get(0); - Object binding = jsmMap.get(securityDomain); - if( binding == null ) + SecurityDomainContext securityDomainCtx = (SecurityDomainContext) securityDomainCtxMap.get(securityDomain); + if( securityDomainCtx == null ) { - binding = newSecurityMgr(securityDomain); - jsmMap.put(securityDomain, binding); + securityDomainCtx = newSecurityDomainCtx(securityDomain); + securityDomainCtxMap.put(securityDomain, securityDomainCtx); + log.info("Added "+securityDomain+", "+securityDomainCtx+" to map"); } - // Look for requests against the security manager + Object binding = securityDomainCtx.getSecurityManager(); + // Look for requests against the security domain context if( name.size() == 2 ) { String request = name.get(1); - if( binding instanceof SubjectSecurityManager && request.equals("subject") ) - { - SubjectSecurityManager ssm = (SubjectSecurityManager) binding; - Subject subject = ssm.getActiveSubject(); - binding = subject; - } + binding = securityDomainCtx.lookup(request); } return binding; } @@ -312,11 +383,11 @@ static class DomainEnumeration implements NamingEnumeration { Enumeration domains; - Hashtable jsmMap; - DomainEnumeration(Enumeration domains, Hashtable jsmMap) + Hashtable ctxMap; + DomainEnumeration(Enumeration domains, Hashtable ctxMap) { this.domains = domains; - this.jsmMap = jsmMap; + this.ctxMap = ctxMap; } public void close() @@ -333,7 +404,7 @@ public Object next() { String name = (String) domains.nextElement(); - Object value = jsmMap.get(name); + Object value = ctxMap.get(name); String className = value.getClass().getName(); NameClassPair pair = new NameClassPair(name, className); return pair; @@ -341,6 +412,35 @@ public Object nextElement() { return domains.nextElement(); + } + } + + /** java:/timedCacheFactory ObjectFactory implementation + */ + public static class DefaultCacheObjectFactory implements InvocationHandler, ObjectFactory + { + /** Object factory implementation. This method returns a Context proxy + that is only able to handle a lookup operation for an atomic name of + a security domain. + */ + public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) + throws Exception + { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + Class[] interfaces = {Context.class}; + Context ctx = (Context) Proxy.newProxyInstance(loader, interfaces, this); + return ctx; + } + /** This is the InvocationHandler callback for the Context interface that + was created by out getObjectInstance() method. All this does is create + a new TimedCache instance. + */ + public Object invoke(Object obj, Method method, Object[] args) throws Throwable + { + TimedCachePolicy cachePolicy = new TimedCachePolicy(defaultCacheTimeout, true, defaultCacheResolution); + cachePolicy.init(); + cachePolicy.start(); + return cachePolicy; } } }
_______________________________________________ Jboss-development mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/jboss-development