diff --git a/core/src/main/java/org/acegisecurity/providers/jaas/JaasAuthenticationCallbackHandler.java b/core/src/main/java/org/acegisecurity/providers/jaas/JaasAuthenticationCallbackHandler.java index 5ea77fc60c..754c30200d 100644 --- a/core/src/main/java/org/acegisecurity/providers/jaas/JaasAuthenticationCallbackHandler.java +++ b/core/src/main/java/org/acegisecurity/providers/jaas/JaasAuthenticationCallbackHandler.java @@ -50,29 +50,19 @@ import javax.security.auth.callback.UnsupportedCallbackException; public interface JaasAuthenticationCallbackHandler { //~ Methods ================================================================ - /** - * Called by the JaasAuthenticationProvider before calling the handle - * method for any Callbacks. - * - * @param auth The Authentication object currently being authenticated. - */ - void setAuthentication(Authentication auth); - /** * Handle the Callback. * The handle method will be called for every callback instance sent from * the LoginContext. Meaning that The handle method may be called multiple - * times for a given JaasAuthenticationCallbackHandler, after a single - * call to the {@link - * #setAuthentication(net.sf.acegisecurity.Authentication) - * setAuthentication} method. + * times for a given JaasAuthenticationCallbackHandler. * * @param callback + * @param auth The Authentication object currently being authenticated. * * @throws IOException * @throws UnsupportedCallbackException */ - void handle(Callback callback) + void handle(Callback callback, Authentication auth) throws IOException, UnsupportedCallbackException; } diff --git a/core/src/main/java/org/acegisecurity/providers/jaas/JaasAuthenticationProvider.java b/core/src/main/java/org/acegisecurity/providers/jaas/JaasAuthenticationProvider.java index c3af24c1ca..dbf49f86f7 100644 --- a/core/src/main/java/org/acegisecurity/providers/jaas/JaasAuthenticationProvider.java +++ b/core/src/main/java/org/acegisecurity/providers/jaas/JaasAuthenticationProvider.java @@ -15,6 +15,7 @@ package net.sf.acegisecurity.providers.jaas; +import com.sun.security.auth.login.ConfigFile; import net.sf.acegisecurity.AcegiSecurityException; import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.AuthenticationException; @@ -23,43 +24,38 @@ import net.sf.acegisecurity.providers.AuthenticationProvider; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; import net.sf.acegisecurity.providers.jaas.event.JaasAuthenticationFailedEvent; import net.sf.acegisecurity.providers.jaas.event.JaasAuthenticationSuccessEvent; - import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; - import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextException; - import org.springframework.core.io.Resource; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.auth.login.Configuration; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; import java.io.IOException; - import java.security.Principal; import java.security.Security; - import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.Set; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.UnsupportedCallbackException; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; - /** * An {@link AuthenticationProvider} implementation that retrieves user details * from a JAAS login configuration. - * + * *
* This AuthenticationProvider is capable of validating {@link
* net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken}
* requests contain the correct username and password.
*
* This implementation is backed by a JAAS @@ -69,7 +65,7 @@ import javax.security.auth.login.LoginException; * configuration file containing an index matching the {@link * #setLoginContextName(java.lang.String) loginContextName} property. *
- * + * ** For example: If this JaasAuthenticationProvider were configured in a Spring * WebApplicationContext the xml to set the loginConfiguration could be as @@ -80,7 +76,7 @@ import javax.security.auth.login.LoginException; * </property> * *
- * + * ** The loginContextName should coincide with a given index in the loginConfig * specifed. The loginConfig file used in the JUnit tests appears as the @@ -98,7 +94,7 @@ import javax.security.auth.login.LoginException; * </property> * *
- * + * ** When using JAAS login modules as the authentication source, sometimes the LoginContext @@ -110,7 +106,7 @@ import javax.security.auth.login.LoginException; * CallbackHandler, control is passed to each {@link * JaasAuthenticationCallbackHandler} for each Callback passed. *
- * + * ** {{@link JaasAuthenticationCallbackHandler}s are passed to the * JaasAuthenticationProvider through the {@link @@ -126,7 +122,7 @@ import javax.security.auth.login.LoginException; * </property> * *
- * + * ** After calling LoginContext.login(), the JaasAuthenticationProvider will * retrieve the returned Principals from the Subject @@ -138,7 +134,7 @@ import javax.security.auth.login.LoginException; * method. The returned role will be applied to the Authorization object as a * {@link GrantedAuthority}. *
- * + * ** AuthorityGranters are configured in spring xml as follows... *
@@ -155,7 +151,7 @@ import javax.security.auth.login.LoginException;
* @version $Id$
*/
public class JaasAuthenticationProvider implements AuthenticationProvider,
- InitializingBean, ApplicationContextAware {
+ InitializingBean, ApplicationContextAware {
//~ Instance fields ========================================================
private ApplicationContext context;
@@ -164,11 +160,12 @@ public class JaasAuthenticationProvider implements AuthenticationProvider,
private String loginContextName = "ACEGI";
private AuthorityGranter[] authorityGranters;
private JaasAuthenticationCallbackHandler[] callbackHandlers;
+ private final String SYSPROP = "java.security.auth.login.config";
//~ Methods ================================================================
public void setApplicationContext(ApplicationContext applicationContext)
- throws BeansException {
+ throws BeansException {
this.context = applicationContext;
}
@@ -177,7 +174,6 @@ public class JaasAuthenticationProvider implements AuthenticationProvider,
* granted to the Authentication.
*
* @param authorityGranters AuthorityGranter array
- *
* @see JaasAuthenticationProvider
*/
public void setAuthorityGranters(AuthorityGranter[] authorityGranters) {
@@ -190,7 +186,6 @@ public class JaasAuthenticationProvider implements AuthenticationProvider,
* were ever set.
*
* @return The AuthorityGranter array, or null
- *
* @see #setAuthorityGranters(net.sf.acegisecurity.providers.jaas.AuthorityGranter[])
*/
public AuthorityGranter[] getAuthorityGranters() {
@@ -203,8 +198,7 @@ public class JaasAuthenticationProvider implements AuthenticationProvider,
*
* @param callbackHandlers Array of JAASAuthenticationCallbackHandlers
*/
- public void setCallbackHandlers(
- JaasAuthenticationCallbackHandler[] callbackHandlers) {
+ public void setCallbackHandlers(JaasAuthenticationCallbackHandler[] callbackHandlers) {
this.callbackHandlers = callbackHandlers;
}
@@ -213,7 +207,6 @@ public class JaasAuthenticationProvider implements AuthenticationProvider,
* none are set.
*
* @return the JAASAuthenticationCallbackHandlers.
- *
* @see #setCallbackHandlers(net.sf.acegisecurity.providers.jaas.JaasAuthenticationCallbackHandler[])
*/
public JaasAuthenticationCallbackHandler[] getCallbackHandlers() {
@@ -224,9 +217,8 @@ public class JaasAuthenticationProvider implements AuthenticationProvider,
* Set the JAAS login configuration file.
*
* @param loginConfig Spring
- * Resource
- *
+ * href="http://www.springframework.org/docs/api/org/springframework/core/io/Resource.html">Spring
+ * Resource
* @see JAAS
* Reference
@@ -253,8 +245,7 @@ public class JaasAuthenticationProvider implements AuthenticationProvider,
return loginContextName;
}
- public void setLoginExceptionResolver(
- LoginExceptionResolver loginExceptionResolver) {
+ public void setLoginExceptionResolver(LoginExceptionResolver loginExceptionResolver) {
this.loginExceptionResolver = loginExceptionResolver;
}
@@ -265,22 +256,24 @@ public class JaasAuthenticationProvider implements AuthenticationProvider,
public void afterPropertiesSet() throws Exception {
if (loginConfig == null) {
throw new ApplicationContextException("loginConfig must be set on "
- + getClass());
+ + getClass());
}
if ((loginContextName == null) || "".equals(loginContextName)) {
- throw new ApplicationContextException(
- "loginContextName must be set on " + getClass());
+ throw new ApplicationContextException("loginContextName must be set on " + getClass());
}
- int n = 1;
+ String loginConfigStr = loginConfig.getURL().toString();
- while (Security.getProperty("login.config.url." + n) != null) {
- n++;
+ boolean allowed = "true".equalsIgnoreCase(Security.getProperty("policy.allowSystemProperty"));
+
+ if (allowed) {
+ System.setProperty(SYSPROP, loginConfigStr);
+ } else {
+ setPropertyUsingLoop(loginConfigStr);
}
- Security.setProperty("login.config.url." + n,
- loginConfig.getURL().toString());
+ Configuration.setConfiguration(new ConfigFile());
}
/**
@@ -288,18 +281,16 @@ public class JaasAuthenticationProvider implements AuthenticationProvider,
* and credential
*
* @param auth The Authentication object to be authenticated.
- *
* @return The authenticated Authentication object, with it's
* grantedAuthorities set.
- *
* @throws AuthenticationException This implementation does not handle
- * 'locked' or 'disabled' accounts. This method only throws a
- * AuthenticationServiceException, with the message of the
- * LoginException that will be thrown, should the
- * loginContext.login() method fail.
+ * 'locked' or 'disabled' accounts. This method only throws a
+ * AuthenticationServiceException, with the message of the
+ * LoginException that will be thrown, should the
+ * loginContext.login() method fail.
*/
public Authentication authenticate(Authentication auth)
- throws AuthenticationException {
+ throws AuthenticationException {
if (auth instanceof UsernamePasswordAuthenticationToken) {
UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) auth;
@@ -322,7 +313,7 @@ public class JaasAuthenticationProvider implements AuthenticationProvider,
Set principals = lc.getSubject().getPrincipals();
for (Iterator iterator = principals.iterator();
- iterator.hasNext();) {
+ iterator.hasNext();) {
Principal principal = (Principal) iterator.next();
for (int i = 0; i < authorityGranters.length; i++) {
@@ -338,8 +329,7 @@ public class JaasAuthenticationProvider implements AuthenticationProvider,
}
//Convert the authorities set back to an array and apply it to the token.
- token.setAuthorities((GrantedAuthority[]) authorities.toArray(
- new GrantedAuthority[authorities.size()]));
+ token.setAuthorities((GrantedAuthority[]) authorities.toArray(new GrantedAuthority[authorities.size()]));
//Publish the success event
context.publishEvent(new JaasAuthenticationSuccessEvent(token));
@@ -348,7 +338,7 @@ public class JaasAuthenticationProvider implements AuthenticationProvider,
return token;
} catch (LoginException loginException) {
AcegiSecurityException ase = loginExceptionResolver
- .resolveException(loginException);
+ .resolveException(loginException);
context.publishEvent(new JaasAuthenticationFailedEvent(auth, ase));
throw ase;
@@ -362,6 +352,28 @@ public class JaasAuthenticationProvider implements AuthenticationProvider,
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass);
}
+ private void setPropertyUsingLoop(String loginConfigStr) {
+ boolean alreadySet = false;
+
+ int n = 1;
+ String prefix = "login.config.url.";
+ String existing = null;
+
+ while ((existing = Security.getProperty(prefix + n)) != null) {
+ alreadySet = existing.equals(loginConfigStr);
+
+ if (alreadySet) {
+ break;
+ }
+
+ n++;
+ }
+
+ if (!alreadySet) {
+ Security.setProperty(prefix + n, loginConfigStr);
+ }
+ }
+
//~ Inner Classes ==========================================================
/**
@@ -375,16 +387,14 @@ public class JaasAuthenticationProvider implements AuthenticationProvider,
}
public void handle(Callback[] callbacks)
- throws IOException, UnsupportedCallbackException {
+ throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbackHandlers.length; i++) {
JaasAuthenticationCallbackHandler handler = callbackHandlers[i];
- handler.setAuthentication(authentication);
-
for (int j = 0; j < callbacks.length; j++) {
Callback callback = callbacks[j];
- handler.handle(callback);
+ handler.handle(callback, authentication);
}
}
}
diff --git a/core/src/main/java/org/acegisecurity/providers/jaas/JaasNameCallbackHandler.java b/core/src/main/java/org/acegisecurity/providers/jaas/JaasNameCallbackHandler.java
index d874494055..46ca6df94c 100644
--- a/core/src/main/java/org/acegisecurity/providers/jaas/JaasNameCallbackHandler.java
+++ b/core/src/main/java/org/acegisecurity/providers/jaas/JaasNameCallbackHandler.java
@@ -40,30 +40,20 @@ import javax.security.auth.callback.UnsupportedCallbackException;
*/
public class JaasNameCallbackHandler
implements JaasAuthenticationCallbackHandler {
- //~ Instance fields ========================================================
-
- private Authentication authentication;
-
//~ Methods ================================================================
- public void setAuthentication(Authentication authentication) {
- this.authentication = authentication;
- }
-
/**
* If the callback passed to the 'handle' method is an instance of
* NameCallback, the JaasNameCallbackHandler will call,
- * callback.setName(authentication.getPrincipal().toString()). Where
- * 'authentication' is the {@link Authentication} object used in the
- * {@link #setAuthentication(net.sf.acegisecurity.Authentication)
- * setAuthentication} method.
+ * callback.setName(authentication.getPrincipal().toString()).
*
* @param callback
+ * @param authentication
*
* @throws IOException
* @throws UnsupportedCallbackException
*/
- public void handle(Callback callback)
+ public void handle(Callback callback, Authentication authentication)
throws IOException, UnsupportedCallbackException {
if (callback instanceof NameCallback) {
NameCallback ncb = (NameCallback) callback;
diff --git a/core/src/main/java/org/acegisecurity/providers/jaas/JaasPasswordCallbackHandler.java b/core/src/main/java/org/acegisecurity/providers/jaas/JaasPasswordCallbackHandler.java
index 82813d8346..b0e4346ddd 100644
--- a/core/src/main/java/org/acegisecurity/providers/jaas/JaasPasswordCallbackHandler.java
+++ b/core/src/main/java/org/acegisecurity/providers/jaas/JaasPasswordCallbackHandler.java
@@ -40,31 +40,20 @@ import javax.security.auth.callback.UnsupportedCallbackException;
*/
public class JaasPasswordCallbackHandler
implements JaasAuthenticationCallbackHandler {
- //~ Instance fields ========================================================
-
- private Authentication auth;
-
//~ Methods ================================================================
- public void setAuthentication(Authentication auth) {
- this.auth = auth;
- }
-
/**
* If the callback passed to the 'handle' method is an instance of
* PasswordCallback, the JaasPasswordCallbackHandler will call,
- * callback.setPassword(authentication.getCredentials().toString()). Where
- * 'authentication' is the {@link Authentication} object used in the
- * {@link
- * JaasAuthenticationCallbackHandler#setAuthentication(net.sf.acegisecurity.Authentication)
- * setAuthentication} method.
+ * callback.setPassword(authentication.getCredentials().toString()).
*
* @param callback
+ * @param auth
*
* @throws IOException
* @throws UnsupportedCallbackException
*/
- public void handle(Callback callback)
+ public void handle(Callback callback, Authentication auth)
throws IOException, UnsupportedCallbackException {
if (callback instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback) callback;
diff --git a/core/src/test/java/org/acegisecurity/providers/jaas/JaasAuthenticationProviderTests.java b/core/src/test/java/org/acegisecurity/providers/jaas/JaasAuthenticationProviderTests.java
index 21f6e01ba6..063cef8b8d 100644
--- a/core/src/test/java/org/acegisecurity/providers/jaas/JaasAuthenticationProviderTests.java
+++ b/core/src/test/java/org/acegisecurity/providers/jaas/JaasAuthenticationProviderTests.java
@@ -17,7 +17,12 @@ package net.sf.acegisecurity.providers.jaas;
import junit.framework.TestCase;
-import net.sf.acegisecurity.*;
+import net.sf.acegisecurity.AcegiSecurityException;
+import net.sf.acegisecurity.Authentication;
+import net.sf.acegisecurity.AuthenticationException;
+import net.sf.acegisecurity.GrantedAuthority;
+import net.sf.acegisecurity.GrantedAuthorityImpl;
+import net.sf.acegisecurity.LockedException;
import net.sf.acegisecurity.providers.TestingAuthenticationToken;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
@@ -25,6 +30,10 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import java.net.URL;
+
+import java.security.Security;
+
import java.util.Arrays;
import java.util.List;
@@ -72,6 +81,17 @@ public class JaasAuthenticationProviderTests extends TestCase {
assertNull("Success event was fired", eventCheck.successEvent);
}
+ public void testConfigurationLoop() throws Exception {
+ String resName = "/" + getClass().getName().replace('.', '/') + ".conf";
+ URL url = getClass().getResource(resName);
+
+ Security.setProperty("policy.allowSystemProperty", "false");
+ Security.setProperty("login.config.url.1", url.toString());
+
+ setUp();
+ testFull();
+ }
+
public void testDetectsMissingLoginConfig() throws Exception {
JaasAuthenticationProvider myJaasProvider = new JaasAuthenticationProvider();
myJaasProvider.setApplicationContext(context);
diff --git a/core/src/test/java/org/acegisecurity/providers/jaas/TestCallbackHandler.java b/core/src/test/java/org/acegisecurity/providers/jaas/TestCallbackHandler.java
index f694edf159..5b67ca6d65 100644
--- a/core/src/test/java/org/acegisecurity/providers/jaas/TestCallbackHandler.java
+++ b/core/src/test/java/org/acegisecurity/providers/jaas/TestCallbackHandler.java
@@ -25,23 +25,15 @@ import javax.security.auth.callback.UnsupportedCallbackException;
/**
- * DOCUMENT ME!
+ * TestCallbackHandler
*
* @author Ray Krueger
* @version $Id$
*/
public class TestCallbackHandler implements JaasAuthenticationCallbackHandler {
- //~ Instance fields ========================================================
-
- Authentication auth;
-
//~ Methods ================================================================
- public void setAuthentication(Authentication auth) {
- this.auth = auth;
- }
-
- public void handle(Callback callback)
+ public void handle(Callback callback, Authentication auth)
throws IOException, UnsupportedCallbackException {
if (callback instanceof TextInputCallback) {
TextInputCallback tic = (TextInputCallback) callback;
diff --git a/core/src/test/resources/org/acegisecurity/providers/jaas/JaasAuthenticationProviderTests.conf b/core/src/test/resources/org/acegisecurity/providers/jaas/JaasAuthenticationProviderTests.conf
new file mode 100644
index 0000000000..272ca7c1af
--- /dev/null
+++ b/core/src/test/resources/org/acegisecurity/providers/jaas/JaasAuthenticationProviderTests.conf
@@ -0,0 +1,3 @@
+JAASTest2 {
+ net.sf.acegisecurity.providers.jaas.TestLoginModule required;
+};
\ No newline at end of file