From 3bd6c597fd4e8aaf3049368a0790f2520c6580b2 Mon Sep 17 00:00:00 2001 From: David BRASSELY Date: Fri, 28 Feb 2014 23:49:35 +0100 Subject: [PATCH] Add SecurityProvider implementation basd on Apache Shiro --- .../standalone/framework/JSEJBIFramework.java | 20 +++-- .../framework/JSEPlatformContext.java | 8 +- openesb-standalone-packaging/pom.xml | 12 +++ .../src/main/assembly/distribution.xml | 2 + .../security/SecurityProviderImpl.java | 76 ++++++++++--------- ...thenticator.java => JMXauthenticator.java} | 4 +- .../security/realm/AbstractRealm.java | 35 +++++++++ .../standalone/security/realm/Realm.java | 17 +++++ .../security/realm/RealmBuilder.java | 31 ++++++++ .../security/realm/RealmHandler.java | 15 ++++ .../security/realm/impl/PropertiesRealm.java | 44 +++++++++++ .../realm/impl/PropertiesRealmHandler.java | 59 ++++++++++++++ .../realm/shiro/PropertiesRealmConverter.java | 26 +++++++ .../security/realm/shiro/RealmConverter.java | 13 ++++ .../realm/shiro/ShiroAuthenticator.java | 54 +++++++++++++ ...esb.standalone.security.realm.RealmHandler | 1 + 16 files changed, 373 insertions(+), 44 deletions(-) rename openesb-standalone-security/src/main/java/net/openesb/standalone/security/auth/login/{CustomJMXAuthenticator.java => JMXauthenticator.java} (87%) create mode 100644 openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/AbstractRealm.java create mode 100644 openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/Realm.java create mode 100644 openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/RealmBuilder.java create mode 100644 openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/RealmHandler.java create mode 100644 openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/impl/PropertiesRealm.java create mode 100644 openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/impl/PropertiesRealmHandler.java create mode 100644 openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/shiro/PropertiesRealmConverter.java create mode 100644 openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/shiro/RealmConverter.java create mode 100644 openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/shiro/ShiroAuthenticator.java create mode 100644 openesb-standalone-security/src/main/resources/META-INF/services/net.openesb.standalone.security.realm.RealmHandler diff --git a/openesb-standalone-framework/src/main/java/net/openesb/standalone/framework/JSEJBIFramework.java b/openesb-standalone-framework/src/main/java/net/openesb/standalone/framework/JSEJBIFramework.java index cb1e896..ad05738 100644 --- a/openesb-standalone-framework/src/main/java/net/openesb/standalone/framework/JSEJBIFramework.java +++ b/openesb-standalone-framework/src/main/java/net/openesb/standalone/framework/JSEJBIFramework.java @@ -47,7 +47,9 @@ import javax.management.ObjectName; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; -import net.openesb.standalone.security.auth.login.CustomJMXAuthenticator; +import javax.naming.Context; +import net.openesb.standalone.security.SecurityProviderImpl; +import net.openesb.standalone.security.auth.login.JMXauthenticator; //import net.openesb.standalone.node.Node; //import net.openesb.standalone.node.NodeBuilder; import net.openesb.standalone.settings.ImmutableSettings; @@ -114,16 +116,19 @@ public class JSEJBIFramework mLog.log(Level.FINE, "Trying to load configuration from {0}", configFile); + Map configurations = null; + try { Yaml yaml = new Yaml(new Constructor(), new Representer(), new DumperOptions(), new Resolver() { @Override protected void addImplicitResolvers() { - //super.addImplicitResolvers(); //To change body of generated methods, choose Tools | Templates. } }); InputStream input = new FileInputStream(new File(configFile)); - settings = new ImmutableSettings((Map) yaml.load(input)); + configurations = (Map) yaml.load(input); + + settings = new ImmutableSettings(configurations); mLog.log(Level.FINE, "Configuration loaded from {0}", configFile); } catch (FileNotFoundException fnfe) { mLog.log(Level.WARNING, "Unable to load configuration file {0}. Default configuration will be used.", configFile); @@ -135,8 +140,9 @@ public class JSEJBIFramework settings.get(INSTANCE_NAME, DEFAULT_INSTANCE_NAME), settings.getAsInt(CONNECTOR_PORT, DEFAULT_CONNECTOR_PORT)); - // Do it in the main thread, not during an RMI connection - // SecurityProvider.getSecurityProvider(); + mPlatformContext.setSecurityProvider( + new SecurityProviderImpl( + (Map>) configurations.get("realm"))); } /** @@ -270,9 +276,9 @@ public class JSEJBIFramework // Create an RMI registry instance to hold the JMX connector server mRegistry = LocateRegistry.createRegistry(port); - map.put(JMXConnectorServer.AUTHENTICATOR, new CustomJMXAuthenticator( + map.put(JMXConnectorServer.AUTHENTICATOR, new JMXauthenticator( mPlatformContext.getSecurityProvider())); - map.put("java.naming.factory.initial", RegistryContextFactory.class.getName()); + map.put(Context.INITIAL_CONTEXT_FACTORY, RegistryContextFactory.class.getName()); map.put("com.sun.management.jmxremote.authenticate", Boolean.TRUE.toString()); // Create and start the connector server diff --git a/openesb-standalone-framework/src/main/java/net/openesb/standalone/framework/JSEPlatformContext.java b/openesb-standalone-framework/src/main/java/net/openesb/standalone/framework/JSEPlatformContext.java index 4695750..d822991 100644 --- a/openesb-standalone-framework/src/main/java/net/openesb/standalone/framework/JSEPlatformContext.java +++ b/openesb-standalone-framework/src/main/java/net/openesb/standalone/framework/JSEPlatformContext.java @@ -423,8 +423,14 @@ public class JSEPlatformContext implements com.sun.jbi.platform.PlatformContext Logger.getLogger(JBI_LOGGER_NAME).setLevel(level); } + private SecurityProvider securityProvider; + + public void setSecurityProvider(SecurityProvider securityProvider) { + this.securityProvider = securityProvider; + } + @Override public SecurityProvider getSecurityProvider() { - return new SecurityProviderImpl(); + return securityProvider; } } diff --git a/openesb-standalone-packaging/pom.xml b/openesb-standalone-packaging/pom.xml index ad473af..dd1f953 100644 --- a/openesb-standalone-packaging/pom.xml +++ b/openesb-standalone-packaging/pom.xml @@ -57,6 +57,11 @@ openesb-standalone-naming ${project.version} + + net.open-esb.runtime.standalone + openesb-standalone-security + ${project.version} + @@ -101,6 +106,13 @@ 5.0.3 + + + org.apache.shiro + shiro-core + ${shiro.version} + + net.open-esb diff --git a/openesb-standalone-packaging/src/main/assembly/distribution.xml b/openesb-standalone-packaging/src/main/assembly/distribution.xml index 7f9550b..479d9fe 100644 --- a/openesb-standalone-packaging/src/main/assembly/distribution.xml +++ b/openesb-standalone-packaging/src/main/assembly/distribution.xml @@ -96,6 +96,7 @@ org.apache.tomcat:tomcat-juli org.apache.tomcat:tomcat-catalina org.yaml:snakeyaml + org.apache.shiro:shiro-core lib/ext false @@ -108,6 +109,7 @@ net.open-esb.runtime.standalone:openesb-standalone-framework net.open-esb.runtime.standalone:openesb-standalone-bootstrap net.open-esb.runtime.standalone:openesb-standalone-naming + net.open-esb.runtime.standalone:openesb-standalone-security false diff --git a/openesb-standalone-security/src/main/java/net/openesb/standalone/security/SecurityProviderImpl.java b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/SecurityProviderImpl.java index 01321e6..88f8614 100644 --- a/openesb-standalone-security/src/main/java/net/openesb/standalone/security/SecurityProviderImpl.java +++ b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/SecurityProviderImpl.java @@ -10,9 +10,9 @@ import javax.security.auth.Subject; import net.openesb.security.AuthenticationException; import net.openesb.security.AuthenticationToken; import net.openesb.security.SecurityProvider; -import org.apache.shiro.authc.UsernamePasswordToken; -import org.apache.shiro.mgt.DefaultSecurityManager; -import org.apache.shiro.realm.text.PropertiesRealm; +import net.openesb.standalone.security.realm.Realm; +import net.openesb.standalone.security.realm.RealmBuilder; +import net.openesb.standalone.security.realm.shiro.ShiroAuthenticator; /** * @@ -21,59 +21,67 @@ import org.apache.shiro.realm.text.PropertiesRealm; */ public class SecurityProviderImpl implements SecurityProvider { - private Logger mLog = + private final Logger mLog = Logger.getLogger(this.getClass().getPackage().getName()); - private final Map securityManagers = - new HashMap(); + private final Map realms = new HashMap(); + private final ShiroAuthenticator authenticator = new ShiroAuthenticator(); + private String adminRealmName = null; - public SecurityProviderImpl() { - this.init(); + public SecurityProviderImpl(Map> realmsConfiguration) { + this.init(realmsConfiguration); + this.validate(); } - private void init() { - mLog.log(Level.INFO, "Loading Realms from configuration."); + private void init(Map> realmsConfiguration) { + if (realmsConfiguration != null) { + mLog.log(Level.INFO, "Loading realms from configuration file."); - PropertiesRealm propertiesRealm = new PropertiesRealm(); - propertiesRealm.setResourcePath("/Users/david/test.properties"); - propertiesRealm.init(); - - securityManagers.put("admin-realm", new DefaultSecurityManager(propertiesRealm)); + for(Map.Entry> realmConfig : realmsConfiguration.entrySet()) { + Realm realm = RealmBuilder. + realmBuilder(). + build(realmConfig.getKey(), realmConfig.getValue()); + + realms.put(realmConfig.getKey(), realm); + } + } else { + mLog.log(Level.WARNING, "No realm defined !"); + } + } + + private void validate() { + for(Realm realm : realms.values()) { + authenticator.loadRealm(realm); + + if (realm.isAdmin()) { + if (adminRealmName == null) { + adminRealmName = realm.getName(); + } else { + throw new IllegalStateException( + "Admin realm already defined: " + adminRealmName); + } + } + } } @Override public Collection getRealms() { return Collections.unmodifiableSet( - securityManagers.keySet()); + realms.keySet()); } @Override public String getAdminRealm() { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + return adminRealmName; } @Override public boolean isAvailable(String realmName) { - return securityManagers.containsKey(realmName); + return realms.containsKey(realmName); } @Override public Subject login(String realmName, AuthenticationToken authenticationToken) throws AuthenticationException { - org.apache.shiro.mgt.SecurityManager securityManager = securityManagers.get(realmName); - org.apache.shiro.subject.Subject currentUser = - new org.apache.shiro.subject.Subject.Builder(securityManager).buildSubject(); - - UsernamePasswordToken token = new UsernamePasswordToken( - (String) authenticationToken.getPrincipal(), - (char []) authenticationToken.getCredentials()); - - try { - currentUser.login(token); - - Subject subject = new Subject(); - return subject; - } catch (org.apache.shiro.authc.AuthenticationException ae) { - throw new AuthenticationException(ae.getMessage()); - } + return authenticator.authenticate(realmName, authenticationToken); } } diff --git a/openesb-standalone-security/src/main/java/net/openesb/standalone/security/auth/login/CustomJMXAuthenticator.java b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/auth/login/JMXauthenticator.java similarity index 87% rename from openesb-standalone-security/src/main/java/net/openesb/standalone/security/auth/login/CustomJMXAuthenticator.java rename to openesb-standalone-security/src/main/java/net/openesb/standalone/security/auth/login/JMXauthenticator.java index 7378722..1abd99c 100644 --- a/openesb-standalone-security/src/main/java/net/openesb/standalone/security/auth/login/CustomJMXAuthenticator.java +++ b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/auth/login/JMXauthenticator.java @@ -11,11 +11,11 @@ import net.openesb.security.UsernamePasswordToken; * @author David BRASSELY (brasseld at gmail.com) * @author OpenESB Community */ -public class CustomJMXAuthenticator implements JMXAuthenticator { +public class JMXauthenticator implements JMXAuthenticator { private final SecurityProvider securityProvider; - public CustomJMXAuthenticator(final SecurityProvider securityProvider) { + public JMXauthenticator(final SecurityProvider securityProvider) { this.securityProvider = securityProvider; } diff --git a/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/AbstractRealm.java b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/AbstractRealm.java new file mode 100644 index 0000000..e62905e --- /dev/null +++ b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/AbstractRealm.java @@ -0,0 +1,35 @@ +package net.openesb.standalone.security.realm; + +/** + * + * @author David BRASSELY (brasseld at gmail.com) + * @author OpenESB Community + */ +public abstract class AbstractRealm implements Realm { + + private String realmName; + private boolean admin = false; + + protected AbstractRealm() { + } + + protected AbstractRealm(String realmName) { + this.realmName = realmName; + } + + public boolean isAdmin() { + return admin; + } + + public void setAdmin(boolean admin) { + this.admin = admin; + } + + public String getName() { + return realmName; + } + + public void setName(String realmName) { + this.realmName = realmName; + } +} diff --git a/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/Realm.java b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/Realm.java new file mode 100644 index 0000000..14ef15e --- /dev/null +++ b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/Realm.java @@ -0,0 +1,17 @@ +package net.openesb.standalone.security.realm; + +/** + * + * @author David BRASSELY (brasseld at gmail.com) + * @author OpenESB Community + */ +public interface Realm { + + void setName(String name); + + String getName(); + + boolean isAdmin(); + + void setAdmin(boolean isAdmin); +} diff --git a/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/RealmBuilder.java b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/RealmBuilder.java new file mode 100644 index 0000000..727e7fb --- /dev/null +++ b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/RealmBuilder.java @@ -0,0 +1,31 @@ +package net.openesb.standalone.security.realm; + +import java.util.Map; +import java.util.ServiceLoader; + +/** + * + * @author David BRASSELY (brasseld at gmail.com) + * @author OpenESB Community + */ +public final class RealmBuilder { + + public static RealmBuilder realmBuilder() { + return new RealmBuilder(); + } + + public Realm build(String realmName, Map properties) { + ServiceLoader handlers = ServiceLoader.load(RealmHandler.class); + for(RealmHandler handler : handlers) { + if (handler.canHandle(realmName)) { + Realm realm = handler.create(properties); + realm.setName(realmName); + + return realm; + } + } + + throw new IllegalStateException("Unable to create realm " + realmName + + " : no handler found !"); + } +} diff --git a/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/RealmHandler.java b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/RealmHandler.java new file mode 100644 index 0000000..ba3a33a --- /dev/null +++ b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/RealmHandler.java @@ -0,0 +1,15 @@ +package net.openesb.standalone.security.realm; + +import java.util.Map; + +/** + * + * @author David BRASSELY (brasseld at gmail.com) + * @author OpenESB Community + */ +public interface RealmHandler { + + boolean canHandle(String type); + + T create(Map properties); +} diff --git a/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/impl/PropertiesRealm.java b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/impl/PropertiesRealm.java new file mode 100644 index 0000000..d9efdaa --- /dev/null +++ b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/impl/PropertiesRealm.java @@ -0,0 +1,44 @@ +package net.openesb.standalone.security.realm.impl; + +import net.openesb.standalone.security.realm.AbstractRealm; + +/** + * + * @author David BRASSELY (brasseld at gmail.com) + * @author OpenESB Community + */ +public class PropertiesRealm extends AbstractRealm { + + private String path; + + private boolean reload = false; + + /** + * Unit: seconds + */ + private int reloadInterval; + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public boolean isReload() { + return reload; + } + + public void setReload(boolean reload) { + this.reload = reload; + } + + public int getReloadInterval() { + return reloadInterval; + } + + public void setReloadInterval(int reloadInterval) { + this.reloadInterval = reloadInterval; + } +} diff --git a/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/impl/PropertiesRealmHandler.java b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/impl/PropertiesRealmHandler.java new file mode 100644 index 0000000..f656ab9 --- /dev/null +++ b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/impl/PropertiesRealmHandler.java @@ -0,0 +1,59 @@ +package net.openesb.standalone.security.realm.impl; + +import java.io.File; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import net.openesb.standalone.security.realm.RealmHandler; + +/** + * + * @author David BRASSELY (brasseld at gmail.com) + * @author OpenESB Community + */ +public class PropertiesRealmHandler implements RealmHandler { + + private final Logger mLog = + Logger.getLogger(this.getClass().getPackage().getName()); + + private final static String PROPERTIES_REALM = "properties"; + + private final static String PROPERTY_PATH = "file"; + private final static String PROPERTY_RELOAD_ENABLE = "reload"; + private final static String PROPERTY_RELOAD_INTERVAL = "interval"; + + @Override + public boolean canHandle(String type) { + return PROPERTIES_REALM.equalsIgnoreCase(type); + } + + @Override + public PropertiesRealm create(Map properties) { + String file = properties.get(PROPERTY_PATH); + mLog.log(Level.INFO, "Creating properties realm using file: {0}", file); + + File propertyFile = new File(file); + if (! propertyFile.exists()) { + mLog.log(Level.SEVERE, "Properties realm, invalid path: {0}", + propertyFile.getAbsolutePath()); + throw new IllegalStateException("Properties realm, invalid path: " + + propertyFile.getAbsolutePath()); + } + + boolean reload = Boolean.parseBoolean(properties.get(PROPERTY_RELOAD_ENABLE)); + PropertiesRealm propertiesRealm = new PropertiesRealm(); + propertiesRealm.setPath(propertyFile.getAbsolutePath()); + + if (reload) { + String sInterval = properties.get(PROPERTY_RELOAD_INTERVAL); + try { + int interval = Integer.parseInt(sInterval); + propertiesRealm.setReloadInterval(interval); + } catch (NumberFormatException nfe) { + + } + } + + return propertiesRealm; + } +} diff --git a/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/shiro/PropertiesRealmConverter.java b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/shiro/PropertiesRealmConverter.java new file mode 100644 index 0000000..9e80bb8 --- /dev/null +++ b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/shiro/PropertiesRealmConverter.java @@ -0,0 +1,26 @@ +package net.openesb.standalone.security.realm.shiro; + +import org.apache.shiro.realm.text.PropertiesRealm; + + +/** + * + * @author David BRASSELY (brasseld at gmail.com) + * @author OpenESB Community + */ +public class PropertiesRealmConverter implements + RealmConverter { + + @Override + public PropertiesRealm convert(net.openesb.standalone.security.realm.impl.PropertiesRealm realm) { + PropertiesRealm cRealm = new PropertiesRealm(); + cRealm.setResourcePath(realm.getPath()); + + if (realm.isReload()) { + cRealm.setReloadIntervalSeconds(realm.getReloadInterval()); + } + + return cRealm; + } + +} diff --git a/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/shiro/RealmConverter.java b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/shiro/RealmConverter.java new file mode 100644 index 0000000..e5a1a19 --- /dev/null +++ b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/shiro/RealmConverter.java @@ -0,0 +1,13 @@ +package net.openesb.standalone.security.realm.shiro; + +import net.openesb.standalone.security.realm.Realm; + +/** + * + * @author David BRASSELY (brasseld at gmail.com) + * @author OpenESB Community + */ +public interface RealmConverter { + + S convert(T realm); +} diff --git a/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/shiro/ShiroAuthenticator.java b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/shiro/ShiroAuthenticator.java new file mode 100644 index 0000000..6ad78df --- /dev/null +++ b/openesb-standalone-security/src/main/java/net/openesb/standalone/security/realm/shiro/ShiroAuthenticator.java @@ -0,0 +1,54 @@ +package net.openesb.standalone.security.realm.shiro; + +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; +import javax.security.auth.Subject; +import net.openesb.security.AuthenticationException; +import net.openesb.security.AuthenticationToken; +import net.openesb.standalone.security.realm.Realm; +import net.openesb.standalone.security.realm.impl.PropertiesRealm; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.mgt.DefaultSecurityManager; + +/** + * + * @author David BRASSELY (brasseld at gmail.com) + * @author OpenESB Community + */ +public class ShiroAuthenticator { + + private final Logger mLog = + Logger.getLogger(this.getClass().getPackage().getName()); + + private final Map securityManagers = + new HashMap(); + + public void loadRealm(Realm realm) { + //TODO: find a way to automate the convertion + org.apache.shiro.realm.Realm sRealm = new PropertiesRealmConverter().convert((PropertiesRealm)realm); + + DefaultSecurityManager manager = new DefaultSecurityManager(sRealm); + securityManagers.put(realm.getName(), manager); + } + + public Subject authenticate(String realmName, AuthenticationToken authenticationToken) + throws AuthenticationException { + org.apache.shiro.mgt.SecurityManager securityManager = securityManagers.get(realmName); + org.apache.shiro.subject.Subject currentUser = + new org.apache.shiro.subject.Subject.Builder(securityManager).buildSubject(); + + UsernamePasswordToken token = new UsernamePasswordToken( + (String) authenticationToken.getPrincipal(), + (char []) authenticationToken.getCredentials()); + + try { + currentUser.login(token); + + Subject subject = new Subject(); + return subject; + } catch (org.apache.shiro.authc.AuthenticationException ae) { + throw new AuthenticationException(ae.getMessage()); + } + } +} diff --git a/openesb-standalone-security/src/main/resources/META-INF/services/net.openesb.standalone.security.realm.RealmHandler b/openesb-standalone-security/src/main/resources/META-INF/services/net.openesb.standalone.security.realm.RealmHandler new file mode 100644 index 0000000..c2ca610 --- /dev/null +++ b/openesb-standalone-security/src/main/resources/META-INF/services/net.openesb.standalone.security.realm.RealmHandler @@ -0,0 +1 @@ +net.openesb.standalone.security.realm.shiro.PropertiesRealmHandler \ No newline at end of file