From dcd4aed1069afb0d77bbbc96cfb7f1f5ae0436c5 Mon Sep 17 00:00:00 2001 From: Adam Lewandowski Date: Fri, 8 Jun 2012 16:02:13 -0400 Subject: [PATCH] Add properties to BindAuthenticator allowing it to bypass user attribute retrieval or retrieve the attributes using the manager context (instead of the user context). Existing behavior (retrieve attributes, using user context) is preserved as default. --- .../BindAuthenticatorTests.java | 16 +++++ .../authentication/BindAuthenticator.java | 58 +++++++++++++++++-- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/BindAuthenticatorTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/BindAuthenticatorTests.java index 69a1ac0f104..54e601b881a 100644 --- a/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/BindAuthenticatorTests.java +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/BindAuthenticatorTests.java @@ -127,4 +127,20 @@ public void testUserDnPatternReturnsCorrectDn() { authenticator.setUserDnPatterns(new String[] {"cn={0},ou=people"}); assertEquals("cn=Joe,ou=people", authenticator.getUserDns("Joe").get(0)); } + + @Test + public void testRetrieveUserAttributes() { + authenticator.setUserDnPatterns(new String[] {"uid={0},ou=people", "cn={0},ou=people"}); + DirContextOperations user = authenticator.authenticate(new UsernamePasswordAuthenticationToken("mouse, jerry", "jerryspassword")); + assertEquals("Mouse", user.getStringAttribute("sn")); + } + + @Test + public void testDoNotRetrieveUserAttributes() { + authenticator.setUserDnPatterns(new String[] {"uid={0},ou=people", "cn={0},ou=people"}); + authenticator.setRetrieveUserAttributes(false); + DirContextOperations user = authenticator.authenticate(new UsernamePasswordAuthenticationToken("mouse, jerry", "jerryspassword")); + assertNull(user.getStringAttribute("sn")); + } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/BindAuthenticator.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/BindAuthenticator.java index 9ab1c7933b8..5893a8b9c88 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/BindAuthenticator.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/BindAuthenticator.java @@ -36,7 +36,8 @@ /** - * An authenticator which binds as a user. + * An authenticator which binds as a user, optionally retrieving user + * attributes. * * @author Luke Taylor * @@ -47,6 +48,10 @@ public class BindAuthenticator extends AbstractLdapAuthenticator { private static final Log logger = LogFactory.getLog(BindAuthenticator.class); + //~ Instance fields ===================================================================================== + private boolean retrieveUserAttributes = true; + private boolean retrieveAttributesWithManagerContext = false; + //~ Constructors =================================================================================================== /** @@ -113,9 +118,7 @@ private DirContextOperations bindWithDn(String userDnStr, String username, Strin // Check for password policy control PasswordPolicyControl ppolicy = PasswordPolicyControlExtractor.extractControl(ctx); - logger.debug("Retrieving attributes..."); - - Attributes attrs = ctx.getAttributes(userDn, getUserAttributes()); + Attributes attrs = retrieveUserAttribute(userDn, ctx); DirContextAdapter result = new DirContextAdapter(attrs, userDn, ctxSource.getBaseLdapPath()); @@ -142,6 +145,25 @@ private DirContextOperations bindWithDn(String userDnStr, String username, Strin return null; } + + /** + * Retrieves user attributes, using either the user's bind context or the manager context. + */ + protected Attributes retrieveUserAttribute(DistinguishedName userDn,DirContext userContext) throws javax.naming.NamingException { + Attributes attrs = null; + if (retrieveUserAttributes) { + DirContext ctx = null; + if (retrieveAttributesWithManagerContext) { + logger.debug("Retrieving attributes using manager context..."); + ctx = getContextSource().getReadOnlyContext(); + } else { + logger.debug("Retrieving attributes using user context..."); + ctx = userContext; + } + attrs = ctx.getAttributes(userDn, getUserAttributes()); + } + return attrs; + } /** * Allows subclasses to inspect the exception thrown by an attempt to bind with a particular DN. @@ -152,4 +174,32 @@ protected void handleBindException(String userDn, String username, Throwable cau logger.debug("Failed to bind as " + userDn + ": " + cause); } } + + public boolean isRetrieveUserAttributes() { + return retrieveUserAttributes; + } + + /** + * If set to false, no user attributes will be retrieved after binding as + * the user. Default is true. + */ + public void setRetrieveUserAttributes(boolean retrieveUserAttributes) { + this.retrieveUserAttributes = retrieveUserAttributes; + } + + public boolean isRetrieveAttributesWithManagerContext() { + return retrieveAttributesWithManagerContext; + } + + /** + * If set to true (the default), user attributes are retrieved using the + * {@link DirContextOperations} obtained when binding as the user. If set to + * false, the manager context (the {@link ContextSource} supplied as + * constructor argument) is used. + */ + public void setRetrieveAttributesWithManagerContext( + boolean retrieveAttributesWithManagerContext) { + this.retrieveAttributesWithManagerContext = retrieveAttributesWithManagerContext; + } + }