mirror of
https://github.com/nicolabs/ldap-plugin.git
synced 2025-09-07 05:14:24 +02:00
[fixed] Supported LDAP server that doesn't allow anonymous bind. In 1.207. (issue #1132)
git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@8506 71c3de6d-444a-0410-be80-ed276b4c234a Originally-Committed-As: e062f1dad43a12fc1ce81dfc746c81ffaa9cd6a7
This commit is contained in:
parent
a104a1e39b
commit
1873162571
|
@ -8,6 +8,7 @@ import hudson.model.Descriptor;
|
||||||
import hudson.model.Hudson;
|
import hudson.model.Hudson;
|
||||||
import hudson.model.User;
|
import hudson.model.User;
|
||||||
import hudson.util.FormFieldValidator;
|
import hudson.util.FormFieldValidator;
|
||||||
|
import hudson.util.Scrambler;
|
||||||
import hudson.util.spring.BeanBuilder;
|
import hudson.util.spring.BeanBuilder;
|
||||||
import net.sf.json.JSONObject;
|
import net.sf.json.JSONObject;
|
||||||
import org.acegisecurity.AuthenticationManager;
|
import org.acegisecurity.AuthenticationManager;
|
||||||
|
@ -17,6 +18,7 @@ import org.acegisecurity.userdetails.UsernameNotFoundException;
|
||||||
import org.acegisecurity.userdetails.ldap.LdapUserDetails;
|
import org.acegisecurity.userdetails.ldap.LdapUserDetails;
|
||||||
import org.acegisecurity.ldap.search.FilterBasedLdapUserSearch;
|
import org.acegisecurity.ldap.search.FilterBasedLdapUserSearch;
|
||||||
import org.acegisecurity.ldap.LdapUserSearch;
|
import org.acegisecurity.ldap.LdapUserSearch;
|
||||||
|
import org.acegisecurity.ldap.LdapDataAccessException;
|
||||||
import org.kohsuke.stapler.DataBoundConstructor;
|
import org.kohsuke.stapler.DataBoundConstructor;
|
||||||
import org.kohsuke.stapler.QueryParameter;
|
import org.kohsuke.stapler.QueryParameter;
|
||||||
import org.kohsuke.stapler.StaplerRequest;
|
import org.kohsuke.stapler.StaplerRequest;
|
||||||
|
@ -25,6 +27,7 @@ import org.springframework.web.context.WebApplicationContext;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
|
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
|
import javax.naming.Context;
|
||||||
import javax.naming.directory.Attribute;
|
import javax.naming.directory.Attribute;
|
||||||
import javax.naming.directory.Attributes;
|
import javax.naming.directory.Attributes;
|
||||||
import javax.naming.directory.DirContext;
|
import javax.naming.directory.DirContext;
|
||||||
|
@ -89,14 +92,32 @@ public class LDAPSecurityRealm extends SecurityRealm {
|
||||||
Geronimo configuration at http://cwiki.apache.org/GMOxDOC11/ldap-realm.html
|
Geronimo configuration at http://cwiki.apache.org/GMOxDOC11/ldap-realm.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If non-null, we use this and {@link #managerPassword}
|
||||||
|
* when binding to LDAP.
|
||||||
|
*
|
||||||
|
* This is necessary when LDAP doesn't support anonymous access.
|
||||||
|
*/
|
||||||
|
public final String managerDN;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scrambled password, used to first bind to LDAP.
|
||||||
|
*/
|
||||||
|
private final String managerPassword;
|
||||||
|
|
||||||
@DataBoundConstructor
|
@DataBoundConstructor
|
||||||
public LDAPSecurityRealm(String server, String rootDN, String userSearchBase, String userSearch) {
|
public LDAPSecurityRealm(String server, String rootDN, String userSearchBase, String userSearch, String managerDN, String managerPassword) {
|
||||||
this.server = server.trim();
|
this.server = server.trim();
|
||||||
if(Util.fixEmptyAndTrim(rootDN)==null) rootDN=Util.fixNull(inferRootDN(server));
|
if(Util.fixEmptyAndTrim(rootDN)==null) rootDN=Util.fixNull(inferRootDN(server));
|
||||||
this.rootDN = rootDN.trim();
|
this.rootDN = rootDN.trim();
|
||||||
this.userSearchBase = userSearchBase.trim();
|
this.userSearchBase = userSearchBase.trim();
|
||||||
if(Util.fixEmptyAndTrim(userSearch)==null) userSearch="uid={0}";
|
if(Util.fixEmptyAndTrim(userSearch)==null) userSearch="uid={0}";
|
||||||
this.userSearch = userSearch.trim();
|
this.userSearch = userSearch.trim();
|
||||||
|
this.managerDN = Util.fixEmpty(managerDN);
|
||||||
|
if(Util.fixEmpty(managerPassword)==null)
|
||||||
|
this.managerPassword = null;
|
||||||
|
else
|
||||||
|
this.managerPassword = Scrambler.scramble(managerPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,7 +127,12 @@ public class LDAPSecurityRealm extends SecurityRealm {
|
||||||
*/
|
*/
|
||||||
private String inferRootDN(String server) {
|
private String inferRootDN(String server) {
|
||||||
try {
|
try {
|
||||||
DirContext ctx = LdapCtxFactory.getLdapCtxInstance("ldap://"+server+'/', new Hashtable());
|
Hashtable<String,String> props = new Hashtable<String,String>();
|
||||||
|
if(managerDN!=null) {
|
||||||
|
props.put(Context.SECURITY_PRINCIPAL,managerDN);
|
||||||
|
props.put(Context.SECURITY_CREDENTIALS,getManagerPassword());
|
||||||
|
}
|
||||||
|
DirContext ctx = LdapCtxFactory.getLdapCtxInstance("ldap://"+server+'/', props);
|
||||||
Attributes atts = ctx.getAttributes("");
|
Attributes atts = ctx.getAttributes("");
|
||||||
Attribute a = atts.get("defaultNamingContext");
|
Attribute a = atts.get("defaultNamingContext");
|
||||||
if(a!=null) // this entry is available on Active Directory. See http://msdn2.microsoft.com/en-us/library/ms684291(VS.85).aspx
|
if(a!=null) // this entry is available on Active Directory. See http://msdn2.microsoft.com/en-us/library/ms684291(VS.85).aspx
|
||||||
|
@ -124,6 +150,10 @@ public class LDAPSecurityRealm extends SecurityRealm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getManagerPassword() {
|
||||||
|
return Scrambler.descramble(managerPassword);
|
||||||
|
}
|
||||||
|
|
||||||
public String getLDAPURL() {
|
public String getLDAPURL() {
|
||||||
return "ldap://"+server+'/'+Util.fixNull(rootDN);
|
return "ldap://"+server+'/'+Util.fixNull(rootDN);
|
||||||
}
|
}
|
||||||
|
@ -141,7 +171,12 @@ public class LDAPSecurityRealm extends SecurityRealm {
|
||||||
new UserDetailsService() {
|
new UserDetailsService() {
|
||||||
final LdapUserSearch ldapSerach = findBean(LdapUserSearch.class, appContext);
|
final LdapUserSearch ldapSerach = findBean(LdapUserSearch.class, appContext);
|
||||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
|
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
|
||||||
|
try {
|
||||||
return ldapSerach.searchForUser(username);
|
return ldapSerach.searchForUser(username);
|
||||||
|
} catch (LdapDataAccessException e) {
|
||||||
|
LOGGER.log(Level.WARNING, "Failed to search LDAP for username="+username,e);
|
||||||
|
throw new UsernameNotFoundException(e.getMessage(),e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,5 +13,11 @@
|
||||||
<f:entry title="${%User search filter}" help="/help/security/ldap/userSearchFilter.html">
|
<f:entry title="${%User search filter}" help="/help/security/ldap/userSearchFilter.html">
|
||||||
<f:textbox name="ldap.userSearch" value="${instance.userSearch}" />
|
<f:textbox name="ldap.userSearch" value="${instance.userSearch}" />
|
||||||
</f:entry>
|
</f:entry>
|
||||||
|
<f:entry title="${%Manager DN}" help="/help/security/ldap/managerDN.html">
|
||||||
|
<f:textbox name="ldap.managerDN" value="${instance.managerDN}" />
|
||||||
|
</f:entry>
|
||||||
|
<f:entry title="${%Manager Password}" help="/help/security/ldap/managerPassword.html">
|
||||||
|
<f:password name="ldap.managerPassword" value="${instance.managerPassword}" />
|
||||||
|
</f:entry>
|
||||||
</f:advanced>
|
</f:advanced>
|
||||||
</j:jelly>
|
</j:jelly>
|
Loading…
Reference in a new issue