Improve performance of JBoss container adapter (thanks to Sergio Bern�).
This commit is contained in:
parent
8888e072a2
commit
ac3d3483b3
|
@ -25,6 +25,9 @@ import org.jboss.security.SimpleGroup;
|
|||
import org.jboss.security.SimplePrincipal;
|
||||
import org.jboss.security.auth.spi.AbstractServerLoginModule;
|
||||
|
||||
import org.springframework.beans.factory.access.*;
|
||||
import org.springframework.beans.factory.access.SingletonBeanFactoryLocator;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import java.security.Principal;
|
||||
|
@ -53,6 +56,7 @@ import javax.security.auth.login.LoginException;
|
|||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Sergio Berná
|
||||
* @version $Id$
|
||||
*/
|
||||
public class JbossAcegiLoginModule extends AbstractServerLoginModule {
|
||||
|
@ -69,36 +73,100 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
|
|||
Map sharedState, Map options) {
|
||||
super.initialize(subject, callbackHandler, sharedState, options);
|
||||
|
||||
if (super.log.isInfoEnabled()) {
|
||||
super.log.info("initializing jboss login module");
|
||||
}
|
||||
|
||||
this.key = (String) options.get("key");
|
||||
|
||||
if ((key == null) || "".equals(key)) {
|
||||
throw new IllegalArgumentException("key must be defined");
|
||||
}
|
||||
|
||||
String singletonId = (String) options.get("singletonId");
|
||||
|
||||
String appContextLocation = (String) options.get("appContextLocation");
|
||||
|
||||
if ((appContextLocation == null) || "".equals(appContextLocation)) {
|
||||
if ((((singletonId == null) || "".equals(singletonId))
|
||||
&& (appContextLocation == null)) || "".equals(appContextLocation)) {
|
||||
throw new IllegalArgumentException(
|
||||
"appContextLocation must be defined");
|
||||
}
|
||||
|
||||
String beanName = (String) options.get("authenticationManager");
|
||||
|
||||
if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) {
|
||||
if (super.log.isInfoEnabled()) {
|
||||
super.log.info("cannot locate " + appContextLocation);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Cannot locate "
|
||||
+ appContextLocation);
|
||||
}
|
||||
|
||||
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(appContextLocation);
|
||||
Map beans = ctx.getBeansOfType(AuthenticationManager.class, true, true);
|
||||
ClassPathXmlApplicationContext ctx = null;
|
||||
|
||||
if ((singletonId == null) || "".equals(singletonId)) {
|
||||
try {
|
||||
ctx = new ClassPathXmlApplicationContext(appContextLocation);
|
||||
} catch (Exception e) {
|
||||
if (super.log.isInfoEnabled()) {
|
||||
super.log.info("error loading spring context "
|
||||
+ appContextLocation + " " + e);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
"error loading spring context " + appContextLocation + " "
|
||||
+ e);
|
||||
}
|
||||
} else {
|
||||
if (super.log.isInfoEnabled()) {
|
||||
super.log.debug("retrieving singleton instance " + singletonId);
|
||||
}
|
||||
|
||||
BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance();
|
||||
BeanFactoryReference bf = bfl.useBeanFactory(singletonId);
|
||||
ctx = (ClassPathXmlApplicationContext) bf.getFactory();
|
||||
|
||||
if (ctx == null) {
|
||||
if (super.log.isInfoEnabled()) {
|
||||
super.log.info("singleton " + beanName + " does not exists");
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("singleton " + singletonId
|
||||
+ " does not exists");
|
||||
}
|
||||
}
|
||||
|
||||
if ((beanName == null) || "".equals(beanName)) {
|
||||
Map beans = null;
|
||||
|
||||
try {
|
||||
beans = ctx.getBeansOfType(AuthenticationManager.class, true,
|
||||
true);
|
||||
} catch (Exception e) {
|
||||
if (super.log.isInfoEnabled()) {
|
||||
super.log.info("exception in getBeansOfType " + e);
|
||||
}
|
||||
|
||||
throw new IllegalStateException(
|
||||
"spring error in get beans by class");
|
||||
}
|
||||
|
||||
if (beans.size() == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Bean context must contain at least one bean of type AuthenticationManager");
|
||||
}
|
||||
|
||||
String beanName = (String) beans.keySet().iterator().next();
|
||||
authenticationManager = (AuthenticationManager) beans.get(beanName);
|
||||
beanName = (String) beans.keySet().iterator().next();
|
||||
}
|
||||
|
||||
authenticationManager = (AuthenticationManager) ctx.getBean(beanName);
|
||||
|
||||
if (super.log.isInfoEnabled()) {
|
||||
super.log.info("Successfully started JbossSpringLoginModule");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean login() throws LoginException {
|
||||
super.loginOk = false;
|
||||
|
@ -121,13 +189,27 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
|
|||
password = "";
|
||||
}
|
||||
|
||||
if (super.log.isDebugEnabled()) {
|
||||
super.log.debug("checking identity");
|
||||
}
|
||||
|
||||
if (identity == null) {
|
||||
super.log.debug("creating usernamepassword token");
|
||||
|
||||
Authentication request = new UsernamePasswordAuthenticationToken(username,
|
||||
password);
|
||||
Authentication response = null;
|
||||
|
||||
try {
|
||||
if (super.log.isDebugEnabled()) {
|
||||
super.log.debug("attempting authentication");
|
||||
}
|
||||
|
||||
response = authenticationManager.authenticate(request);
|
||||
|
||||
if (super.log.isDebugEnabled()) {
|
||||
super.log.debug("authentication succeded");
|
||||
}
|
||||
} catch (AuthenticationException failed) {
|
||||
if (super.log.isDebugEnabled()) {
|
||||
super.log.debug("Bad password for username=" + username);
|
||||
|
@ -137,6 +219,8 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
|
|||
"Password Incorrect/Password Required");
|
||||
}
|
||||
|
||||
super.log.debug("user is logged. redirecting to jaas classes");
|
||||
|
||||
identity = new PrincipalAcegiUserToken(this.key,
|
||||
response.getPrincipal().toString(),
|
||||
response.getCredentials().toString(),
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<!--
|
||||
* ========================================================================
|
||||
*
|
||||
|
@ -21,7 +20,6 @@
|
|||
*
|
||||
* ========================================================================
|
||||
-->
|
||||
|
||||
<book>
|
||||
<bookinfo>
|
||||
<title>Acegi Security System for Spring</title>
|
||||
|
@ -2479,14 +2477,17 @@ $CATALINA_HOME/bin/startup.sh</programlisting></para>
|
|||
<sect2 id="security-container-adapters-joss">
|
||||
<title>JBoss Installation</title>
|
||||
|
||||
<para>The following was tested with JBoss 3.2.3. We automatically test
|
||||
<para>The following was tested with JBoss 3.2.6. We automatically test
|
||||
the following directions using our container integration test system
|
||||
and this version of JBoss.</para>
|
||||
|
||||
<para><literal>$JBOSS_HOME</literal> refers to the root of your JBoss
|
||||
installation.</para>
|
||||
|
||||
<para>Edit your
|
||||
<para>There are two different ways of making spring context available
|
||||
to the Jboss integration classes. </para>
|
||||
|
||||
<para>The first approach is by editing your
|
||||
<literal>$JBOSS_HOME/server/your_config/conf/login-config.xml</literal>
|
||||
file so that it contains a new entry under the
|
||||
<literal><Policy></literal> section:</para>
|
||||
|
@ -2504,7 +2505,51 @@ $CATALINA_HOME/bin/startup.sh</programlisting></para>
|
|||
<para>Copy <literal>acegisecurity.xml</literal> into
|
||||
<literal>$JBOSS_HOME/server/your_config/conf</literal>.</para>
|
||||
|
||||
<para>Copy the following files into
|
||||
<para>In this configuration <literal>acegisecurity.xml</literal>
|
||||
contains the spring context definition including all the
|
||||
authentication manager beans. You have to bear in mind though, that
|
||||
<literal>SecurityContext</literal> is created and destroyed on each
|
||||
login request, so the login operation might become costly.
|
||||
Alternatively, the second approach is to use Spring singleton
|
||||
capabilities through
|
||||
<literal>org.springframework.beans.factory.access.SingletonBeanFactoryLocator</literal>.
|
||||
The required configuration for this approach is:</para>
|
||||
|
||||
<para><programlisting> <application-policy name = "SpringPoweredRealm">
|
||||
<authentication>
|
||||
<login-module code = "net.sf.acegisecurity.adapters.jboss.JbossSpringLoginModule"
|
||||
flag = "required">
|
||||
<module-option name = "singletonId">springRealm</module-option>
|
||||
<module-option name = "key">my_password</module-option>
|
||||
<module-option name = "authenticationManager">authenticationManager</module-option>
|
||||
</login-module>
|
||||
</authentication>
|
||||
</application-policy></programlisting></para>
|
||||
|
||||
<para>In the above code fragment,
|
||||
<literal>authenticationManager</literal> is a helper property that
|
||||
defines the expected name of the
|
||||
<literal>AuthenticationManager</literal> in case you have several
|
||||
defined in the IoC container. The <literal>singletonId</literal>
|
||||
property references a bean defined in a
|
||||
<literal>beanRefFactory.xml</literal> file. This file needs to be
|
||||
available from anywhere on the JBoss classpath, including
|
||||
<literal>$JBOSS_HOME/server/your_config/conf</literal>. The
|
||||
<literal>beanRefFactory.xml</literal> contains the following
|
||||
declaration:</para>
|
||||
|
||||
<para><programlisting><beans>
|
||||
<bean id="springRealm" singleton="true" lazy-init="true" class="org.springframework.context.support.ClassPathXmlApplicationContext">
|
||||
<constructor-arg>
|
||||
<list>
|
||||
<value>acegisecurity.xml</value>
|
||||
</list>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
</beans></programlisting></para>
|
||||
|
||||
<para>Finally, irrespective of the configuration approach you need to
|
||||
copy the following files into
|
||||
<literal>$JBOSS_HOME/server/your_config/lib</literal>:<itemizedlist>
|
||||
<listitem>
|
||||
<para><literal>aopalliance.jar</literal></para>
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
<action dev="benalex" type="update">Improved BasicAclProvider to only respond to specified ACL object requests</action>
|
||||
<action dev="benalex" type="update">Refactored MethodDefinitionSource to work with Method, not MethodInvocation</action>
|
||||
<action dev="benalex" type="update">Refactored AbstractSecurityInterceptor to better support other AOP libraries</action>
|
||||
<action dev="benalex" type="update">Improved performance of JBoss container adapter (see reference docs)</action>
|
||||
<action dev="benalex" type="fix">Fixed AbstractProcessingFilter to use removeAttribute (JRun compatibility)</action>
|
||||
<action dev="benalex" type="fix">Fixed GrantedAuthorityEffectiveAclResolver support of UserDetails principals</action>
|
||||
<action dev="benalex" type="update">Moved MethodSecurityInterceptor to ...intercept.method.aopalliance package</action>
|
||||
|
|
|
@ -120,6 +120,9 @@
|
|||
<contributor>
|
||||
<name>Andrew Petro</name>
|
||||
</contributor>
|
||||
<contributor>
|
||||
<name>Sergio Berná</name>
|
||||
</contributor>
|
||||
</contributors>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
|
Loading…
Reference in New Issue