提交 adbccfee 编写于 作者: K kohsuke

[FIXED HUDSON-1971] Applying patch from Justin Edelson.

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@10468 71c3de6d-444a-0410-be80-ed276b4c234a
上级 6ada76c0
/**
*
*/
package hudson.security;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.ldap.InitialDirContextFactory;
import org.acegisecurity.ldap.LdapDataAccessException;
import org.acegisecurity.providers.ldap.LdapAuthoritiesPopulator;
import org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator;
import org.acegisecurity.userdetails.ldap.LdapUserDetails;
import org.springframework.util.Assert;
/**
* Implementation of {@link LdapAuthoritiesPopulator} that defers creation of a
* {@link DefaultLdapAuthoritiesPopulator} until one is needed. This is done to
* ensure that the groupSearchBase property can be set.
*
* @author justinedelson
*/
public class DeferredCreationLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator {
/**
* A default role which will be assigned to all authenticated users if set.
*/
private String defaultRole = null;
/**
* An initial context factory is only required if searching for groups is
* required.
*/
private InitialDirContextFactory initialDirContextFactory = null;
/**
* Controls used to determine whether group searches should be performed
* over the full sub-tree from the base DN.
*/
private boolean searchSubtree = false;
/**
* The ID of the attribute which contains the role name for a group
*/
private String groupRoleAttribute = "cn";
/**
* The base DN from which the search for group membership should be
* performed
*/
private String groupSearchBase = null;
/**
* The pattern to be used for the user search. {0} is the user's DN
*/
private String groupSearchFilter = "(member={0})";
private String rolePrefix = "ROLE_";
private boolean convertToUpperCase = true;
/**
* Constructor.
*
* @param initialDirContextFactory
* supplies the contexts used to search for user roles.
* @param groupSearchBase
* if this is an empty string the search will be performed from
* the root DN of the context factory.
*/
public DeferredCreationLdapAuthoritiesPopulator(
InitialDirContextFactory initialDirContextFactory, String groupSearchBase) {
this.setInitialDirContextFactory(initialDirContextFactory);
this.setGroupSearchBase(groupSearchBase);
}
public GrantedAuthority[] getGrantedAuthorities(LdapUserDetails userDetails)
throws LdapDataAccessException {
return create().getGrantedAuthorities(userDetails);
}
public void setConvertToUpperCase(boolean convertToUpperCase) {
this.convertToUpperCase = convertToUpperCase;
}
public void setDefaultRole(String defaultRole) {
this.defaultRole = defaultRole;
}
public void setGroupRoleAttribute(String groupRoleAttribute) {
this.groupRoleAttribute = groupRoleAttribute;
}
public void setGroupSearchBase(String groupSearchBase) {
this.groupSearchBase = groupSearchBase;
}
public void setGroupSearchFilter(String groupSearchFilter) {
this.groupSearchFilter = groupSearchFilter;
}
public void setInitialDirContextFactory(InitialDirContextFactory initialDirContextFactory) {
this.initialDirContextFactory = initialDirContextFactory;
}
public void setRolePrefix(String rolePrefix) {
this.rolePrefix = rolePrefix;
}
public void setSearchSubtree(boolean searchSubtree) {
this.searchSubtree = searchSubtree;
}
/**
* Create a new DefaultLdapAuthoritiesPopulator object.
*
* @return a DefaultLdapAuthoritiesPopulator.
*/
private DefaultLdapAuthoritiesPopulator create() {
Assert
.hasText(groupSearchBase,
"groupSearchBase must be non-null by the time DefaultLdapAuthoritiesPopulator is instantiated.");
DefaultLdapAuthoritiesPopulator populator = new DefaultLdapAuthoritiesPopulator(
initialDirContextFactory, groupSearchBase);
populator.setConvertToUpperCase(convertToUpperCase);
if (defaultRole != null) {
populator.setDefaultRole(defaultRole);
}
populator.setGroupRoleAttribute(groupRoleAttribute);
populator.setGroupSearchFilter(groupSearchFilter);
populator.setRolePrefix(rolePrefix);
populator.setSearchSubtree(searchSubtree);
return populator;
}
}
......@@ -42,6 +42,7 @@ import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* {@link SecurityRealm} implementation that uses LDAP for authentication.
*
......@@ -78,6 +79,15 @@ public class LDAPSecurityRealm extends SecurityRealm {
* @see FilterBasedLdapUserSearch
*/
public final String userSearch;
/**
* This defines the organizational unit that contains groups.
*
* Normally "ou=groups"
*
* @see FilterBasedLdapUserSearch
*/
public final String groupSearchBase;
/*
Other configurations that are needed:
......@@ -106,13 +116,14 @@ public class LDAPSecurityRealm extends SecurityRealm {
private final String managerPassword;
@DataBoundConstructor
public LDAPSecurityRealm(String server, String rootDN, String userSearchBase, String userSearch, String managerDN, String managerPassword) {
public LDAPSecurityRealm(String server, String rootDN, String userSearchBase, String userSearch, String groupSearchBase, String managerDN, String managerPassword) {
this.server = server.trim();
if(Util.fixEmptyAndTrim(rootDN)==null) rootDN=Util.fixNull(inferRootDN(server));
this.rootDN = rootDN.trim();
this.userSearchBase = userSearchBase.trim();
if(Util.fixEmptyAndTrim(userSearch)==null) userSearch="uid={0}";
this.userSearch = userSearch.trim();
this.groupSearchBase = Util.fixEmptyAndTrim(groupSearchBase);
this.managerDN = Util.fixEmpty(managerDN);
if(Util.fixEmpty(managerPassword)==null)
this.managerPassword = null;
......@@ -165,6 +176,7 @@ public class LDAPSecurityRealm extends SecurityRealm {
BeanBuilder builder = new BeanBuilder();
builder.parse(Hudson.getInstance().servletContext.getResourceAsStream("/WEB-INF/security/LDAPBindSecurityRealm.groovy"),binding);
final WebApplicationContext appContext = builder.createApplicationContext();
correctAuthoritiesPopulator(appContext);
return new SecurityComponents(
findBean(AuthenticationManager.class, appContext),
......@@ -181,6 +193,15 @@ public class LDAPSecurityRealm extends SecurityRealm {
});
}
/**
* Adjust the authoritiesPopulator bean to have the correct groupSearchBase
* @param appContext
*/
private void correctAuthoritiesPopulator(WebApplicationContext appContext) {
DeferredCreationLdapAuthoritiesPopulator factory = (DeferredCreationLdapAuthoritiesPopulator) appContext.getBean("authoritiesPopulator");
factory.setGroupSearchBase(groupSearchBase==null ? "ou=groups" : groupSearchBase);
}
/**
* If the security realm is LDAP, try to pick up e-mail address from LDAP.
*/
......
......@@ -13,6 +13,9 @@
<f:entry title="${%User search filter}" help="/help/security/ldap/userSearchFilter.html">
<f:textbox name="ldap.userSearch" value="${instance.userSearch}" />
</f:entry>
<f:entry title="${%Group search base}" help="/help/security/ldap/groupSearchBase.html">
<f:textbox name="ldap.groupSearchBase" value="${instance.groupSearchBase}" />
</f:entry>
<f:entry title="${%Manager DN}" help="/help/security/ldap/managerDN.html">
<f:textbox name="ldap.managerDN" value="${instance.managerDN}"
checkUrl="'${rootURL}/securityRealms/LDAPSecurityRealm/serverCheck?field=managerDN&amp;server='+escape(this.form.elements['ldap.server'].value)+'&amp;managerDN='+escape(this.value)+'&amp;managerPassword='+escape(this.form.elements['ldap.managerPassword'].value)"
......
......@@ -2,11 +2,11 @@ import org.acegisecurity.providers.ProviderManager
import org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider
import org.acegisecurity.providers.ldap.LdapAuthenticationProvider
import org.acegisecurity.providers.ldap.authenticator.BindAuthenticator2
import org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator
import org.acegisecurity.ldap.DefaultInitialDirContextFactory
import org.acegisecurity.ldap.search.FilterBasedLdapUserSearch
import org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider
import hudson.model.Hudson
import hudson.security.DeferredCreationLdapAuthoritiesPopulator
/*
Configure LDAP as the authentication realm.
......@@ -35,7 +35,7 @@ bindAuthenticator(BindAuthenticator2,initialDirContextFactory) {
userSearch = ldapUserSearch;
}
authoritiesPopulator(DefaultLdapAuthoritiesPopulator,initialDirContextFactory,"ou=groups") {
authoritiesPopulator(DeferredCreationLdapAuthoritiesPopulator,initialDirContextFactory,"ou=groups") {
// groupRoleAttribute = "ou";
}
......
<div>
One of the searches Hudson does on LDAP is to locate the list of groups for a user.
<p>
This field determines the query to be run to identify the organizational unit that contains groups. The query is
almost always <tt>"ou=groups"</tt>, so in most cases you should leave this field empty and let this default kick in.
</div>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册