added LDAP search support

This commit is contained in:
Joern Muehlencord
2019-05-28 17:41:10 +02:00
parent 336e76f536
commit be34fa9e8d
4 changed files with 614 additions and 0 deletions

View File

@ -0,0 +1,111 @@
package de.muehlencord.shared.network.ldap;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
/**
* Inits and holds a connection to an ldap address directory
* @see javax.naming.ldap.LdapContext;
* @author dennis.nobel
*/
public class LDAPConnection {
public static final String CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
public static final String CONTROL_FACTORY = "com.sun.jndi.ldap.ControlFactory";
public static final String AUTHENTICATION_SIMPLE = "simple";
public static final String SECURITYPROTOCOL_SIMPLE = "simple";
private String authentication;
private String providerUrl;
private String securityProtocol;
private String username;
private String password;
private LdapContext ldapContext;
public LDAPConnection(String authentication, String providerUrl, String securityProtocol, String username, String password) {
this.authentication = authentication;
this.providerUrl = providerUrl;
this.securityProtocol = securityProtocol;
this.username = username;
this.password = password;
}
public String getAuthentication() {
return authentication;
}
public void setAuthentication(String authentication) {
this.authentication = authentication;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getProviderUrl() {
return providerUrl;
}
public void setProviderUrl(String providerUrl) {
this.providerUrl = providerUrl;
}
public String getSecurityProtocol() {
return securityProtocol;
}
public void setSecurityProtocol(String securityProtocol) {
this.securityProtocol = securityProtocol;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
/**
* intializes connection to AD
* @throws NamingException is thrown if connection to LDAP failed
*/
protected void init() throws NamingException {
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, CONTEXT_FACTORY);
env.put(LdapContext.CONTROL_FACTORIES, CONTROL_FACTORY);
env.put(Context.PROVIDER_URL, providerUrl);
env.put(Context.SECURITY_PRINCIPAL, username);
env.put(Context.SECURITY_CREDENTIALS, password);
env.put(Context.SECURITY_AUTHENTICATION, authentication);
env.put(Context.SECURITY_PROTOCOL, securityProtocol);
ldapContext = new InitialLdapContext(env, null);
}
/**
* @see javax.naming.ldap.LdapContext;
*/
public NamingEnumeration<SearchResult> search(String name, String filter, SearchControls cons) throws NamingException {
return ldapContext.search(name, filter, cons);
}
/**
* @see javax.naming.ldap.LdapContext;
*/
public void close() throws NamingException {
if (ldapContext != null) {
ldapContext.close();
ldapContext = null;
}
}
}

View File

@ -0,0 +1,121 @@
package de.muehlencord.shared.network.ldap;
/**
* Represents a contact in ldap address directory
*
* @author Joern Muehlencord
*/
public class LDAPContact {
/**
* type person
*/
public static final String TYPE_PERSON = "top, person";
/**
* type group
*/
public static final String TYPE_GROUP = "top, group";
/**
* type public folder
*/
public static final String TYPE_PUBLICFOLDER = "top, publicFolder";
private String type = null;
private String lastname = null;
private String firstname = null;
private String crmname = null;
private String emailaddress = null;
private String department = null;
private String phone = null;
private String country = null;
private String countryCode = null;
private boolean isEnabled = false;
private String distinguishedName = null;
public String getType() {
return type;
}
public void setType(String t) {
this.type = t;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
public String getCrmname() {
return crmname;
}
public void setCrmname(String crmname) {
this.crmname = crmname;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getEmailaddress() {
return emailaddress;
}
public void setEmailaddress(String emailaddress) {
this.emailaddress = emailaddress;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public boolean isEnabled() {
return isEnabled;
}
public void setEnabled(boolean isEnabled) {
this.isEnabled = isEnabled;
}
public String getDistinguishedName() {
return this.distinguishedName;
}
public void setDistinguishedName(String distinguishedName) {
this.distinguishedName = distinguishedName.trim();
}
}

View File

@ -0,0 +1,22 @@
package de.muehlencord.shared.network.ldap;
/**
* Exception used as wrapper for exepctions in ldap context
*
* @author Joern Muehlencord
*/
public class LDAPException extends Exception {
/**
* the serial version uid
*/
private static final long serialVersionUID = -6399987658718847425L;
public LDAPException(String message) {
super(message);
}
public LDAPException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,360 @@
package de.muehlencord.shared.network.ldap;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
/**
* Connection to ldap server to searh by different values
*
* @author Joern Muehlencord
*/
public class LDAPSearch {
/**
* the ldap connection to use
*/
private LDAPConnection ldapConnection;
/**
* the search base for all queries
*/
private String searchBase;
/**
* Creates a new instance of a ldap search.
*
* <p>
* Important: <br> If you want to use ldaps - usually port 636 make sure you
* provide a trustkeystore in case your ldap server does not use a
* certificate which can be trusted by the build in root certificates. (e.g.
* self signed certificates) </p>
*
* <p>
* To provide access to a trust center you can specify the following
* parameter to your application by providing the following parameter
* <pre>
* -Djavax.net.ssl.trustStore=/path/to/truststore.keystore
* </pre> </p>
*
* @param url the url of the ldap server to connect to like
* <code>ldap://ldapserver.your.domain:389</code>
* @param searchBase the search base to use - e.g.
* <code>DC=wincor-nixdorf,DC=com</code>
* @param username the username to connect with
* @param password the password to connect with
*/
public LDAPSearch(String url, String searchBase, String username, String password) {
String authentication = LDAPConnection.AUTHENTICATION_SIMPLE;
String securityProtocol = LDAPConnection.SECURITYPROTOCOL_SIMPLE;
this.ldapConnection = new LDAPConnection(authentication, url, securityProtocol, username, password);
this.searchBase = searchBase;
}
/**
* Creates a new instance of a ldap search.
*
* <p>
* Important: <br> If you want to use ldaps - usually port 636 make sure you
* provide a trustkeystore in case your ldap server does not use a
* certificate which can be trusted by the build in root certificates. (e.g.
* self signed certificates) </p>
*
* <p>
* To provide access to a trust center you can specify the following
* parameter to your application by providing the following parameter
* <pre>
* -Djavax.net.ssl.trustStore=/path/to/truststore.keystore
* </pre> </p>
*
* @param authentication the authentification type to use -e.g. "SIMPLE"
* @param url the url of the ldap server to connect to like
* <code>ldap://ldapserver.your.domain:389</code>
* @param securityProtoco the security protocol to use - e.g. SIMPLE
* @param searchBase the search base to use - e.g.
* <code>DC=wincor-nixdorf,DC=com</code>
* @param username the username to connect with
* @param password the password to connect with
*/
public LDAPSearch(String authentication, String url, String securityProtocol, String searchBase, String username, String password) {
this.ldapConnection = new LDAPConnection(authentication, url, securityProtocol, username, password);
this.searchBase = searchBase;
}
/**
* execute several init steps, connect to ldap
*/
public void init() throws LDAPException {
try {
ldapConnection.init();
} catch (NamingException ex) {
throw new LDAPException("Connection refused.", ex);
}
}
/**
* close the ldap connection
*/
public void close() throws LDAPException {
if (ldapConnection != null) {
try {
ldapConnection.close();
ldapConnection = null;
} catch (NamingException ex) {
throw new LDAPException("Connection could not be closed.", ex);
}
}
}
/**
* Returns the search base of the ldap connection
*
* @return the search base of the ldap connection
*/
public String getSearchBase() {
return searchBase;
}
/**
* Searches a contact according to emailaddress in the address directory
*
* @param email emailaddress to search for
* @return ldap contact or null if nothing could be found
* @throws LDAPException when search fails
*/
public LDAPContact searchContactWithEmail(String email) throws LDAPException {
return searchContact("mail", email);
}
public LDAPContact searchContact(String searchField, String searchValue) throws LDAPException {
if (ldapConnection == null) {
throw new LDAPException("No connection established. Please execute init before.", null);
}
// prepare search parameters
String[] resultattributes = {"objectClass", "name", "givenName", "sn", "department", "co", "telephoneNumber", "sAMAccountName", "c",
"userAccountControl", "managedBy", "distinguishedName", "mail"};
String searchfilter = "(" + searchField + "=" + searchValue + ")";
SearchControls searchcontrols = new SearchControls();
String[] resultAttributes = resultattributes;
searchcontrols.setReturningAttributes(resultAttributes);
searchcontrols.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration result;
try {
// search
result = ldapConnection.search(searchBase, searchfilter, searchcontrols);
// process result
Attributes attributes;
if (result.hasMoreElements()) {
SearchResult searchresult = (SearchResult) result.next();
attributes = searchresult.getAttributes();
} else {
// clearly nothing found
return null;
}
// create contact from search attributes
LDAPContact ldapContact = createLDAPContact(attributes);
return ldapContact;
} catch (NamingException ex) {
throw new LDAPException("Search failed for unkown reason.", ex);
}
}
/**
* Returns true, if the given email address can be found in the configured
* ldap
*
* @param email the emailaddress to search for
* @return true, if the email address could be found; else false
* @throws LDAPException if the search fails
*/
public boolean emailExists(String email) throws LDAPException {
return searchContactWithEmail(email) != null;
}
/**
* Returns true, if the given email address is member of the given group,
* specified by the DN
*
* @param email the email to validat
* @param groupDn the group search base - all members must be found as
* "member" in this group
* @return
*/
public boolean isMemberOfGroup(String email, String groupDn) throws LDAPException {
boolean returnValue = false;
LDAPContact contact = searchContactWithEmail(email);
if (contact == null) {
return false;
}
// prepare search parameters
String[] resultattributes = {"member"};
String searchfilter = "(objectClass=*)";
SearchControls searchcontrols = new SearchControls();
String[] resultAttributes = resultattributes;
searchcontrols.setReturningAttributes(resultAttributes);
searchcontrols.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration result;
try {
result = ldapConnection.search(groupDn, searchfilter, searchcontrols);
while (result.hasMoreElements()) {
SearchResult searchresult = (SearchResult) result.next();
Attributes attributes = searchresult.getAttributes();
if ((attributes.get("member")) != null) {
String memberList = attributes.get("member").toString();
if (memberList == null) {
return false;
}
returnValue = memberList.contains(contact.getDistinguishedName());
} else {
// if
return false;
}
}
} catch (NamingException ex) {
throw new LDAPException(ex.getMessage(), ex);
}
return returnValue;
}
private LDAPContact createLDAPContact(Attributes attributes) throws LDAPException {
LDAPContact ldapContact = new LDAPContact();
if (attributes.get("mail") != null) {
ldapContact.setEmailaddress(attributes.get("mail").toString());
} else {
ldapContact.setEmailaddress("");
}
if (attributes.get("objectClass") != null) {
String objectClass = attributes.get("objectClass").toString();
if (objectClass.contains(":")) {
objectClass = objectClass.substring(objectClass.indexOf(":") + 2);
}
if (objectClass.startsWith(LDAPContact.TYPE_PERSON)) {
ldapContact.setType(LDAPContact.TYPE_PERSON);
} else if (objectClass.startsWith(LDAPContact.TYPE_PUBLICFOLDER)) {
ldapContact.setType(LDAPContact.TYPE_PUBLICFOLDER);
} else if (objectClass.startsWith(LDAPContact.TYPE_GROUP)) {
ldapContact.setType(LDAPContact.TYPE_GROUP);
} else {
throw new LDAPException("Invalid objectClass " + objectClass + " found. ", null);
}
}
switch (ldapContact.getType()) {
case LDAPContact.TYPE_PERSON:
// handle persons
// get mandatory fields from ad entry
if (attributes.get("distinguishedName") != null) {
String distinguishedName = attributes.get("distinguishedName").toString();
distinguishedName = distinguishedName.substring(distinguishedName.indexOf(":") + 2);
ldapContact.setDistinguishedName(distinguishedName);
}
if (attributes.get("givenName") != null) {
String firstname = attributes.get("givenName").toString();
firstname = firstname.substring(firstname.indexOf(":") + 2);
ldapContact.setFirstname(firstname);
}
if (attributes.get("sn") != null) {
String lastname = attributes.get("sn").toString();
lastname = lastname.substring(lastname.indexOf(":") + 2);
ldapContact.setLastname(lastname);
}
if (attributes.get("c") != null) {
String countryCode = attributes.get("c").toString();
countryCode = countryCode.substring(countryCode.indexOf(":") + 2);
ldapContact.setCountryCode(countryCode);
}
if (attributes.get("co") != null) {
String country = attributes.get("co").toString();
country = country.substring(country.indexOf(":") + 2);
ldapContact.setCountry(country);
}
if (attributes.get("department") != null) {
String department = attributes.get("department").toString();
department = department.substring(department.indexOf(":") + 2);
ldapContact.setDepartment(department);
}
if (attributes.get("telephoneNumber") != null) {
String phone = attributes.get("telephoneNumber").toString();
phone = phone.substring(phone.indexOf(":") + 2);
ldapContact.setPhone(phone);
}
if (attributes.get("sAMAccountName") != null) {
String crmname = attributes.get("sAMAccountName").toString().toLowerCase();
crmname = crmname.substring(crmname.indexOf(":") + 2);
ldapContact.setCrmname(crmname);
}
if (attributes.get("userAccountControl") != null) {
String userAccountControl = attributes.get("userAccountControl").toString();
userAccountControl = userAccountControl.substring(userAccountControl.indexOf(":") + 2);
if (userAccountControl.equals("512")) {
ldapContact.setEnabled(true);
} else {
ldapContact.setEnabled(false);
}
} else {
ldapContact.setEnabled(false);
}
break;
case LDAPContact.TYPE_GROUP:
case LDAPContact.TYPE_PUBLICFOLDER:
// handle groups
ldapContact.setEnabled(true);
ldapContact.setFirstname("Group");
if (attributes.get("name") != null) {
String name = attributes.get("name").toString().toLowerCase();
name = name.substring(name.indexOf(":") + 2);
ldapContact.setLastname(name);
} else {
String lastName = ldapContact.getEmailaddress();
lastName = lastName.substring(0, lastName.indexOf("@") - 1);
ldapContact.setLastname(lastName);
}
if (attributes.get("managedBy") != null) {
try {
String managedBy = attributes.get("managedBy").toString().toLowerCase();
managedBy = managedBy.substring(managedBy.indexOf(":") + 2);
managedBy = managedBy.substring(managedBy.lastIndexOf("ou="));
managedBy = managedBy.substring(3, managedBy.indexOf(","));
ldapContact.setCountry(managedBy);
} catch (Exception ex) {
ldapContact.setCountry(null);
}
}
break;
default:
throw new LDAPException("Unknown / unsupported ldap type " + ldapContact.getType());
}
return ldapContact;
}
}
/**
* History:
*
* $$Log: src/main/java/com/wincornixdorf/shared/network/ldap/LDAPSearch.java $
* Revision 1.1 2013/12/16 16:42:52MEZ Muehlencord, Joern (joern.muehlencord)
* Initial revision Member added to project
* m:/MKS/ESP_Tools/shared/shared-network/shared-network.pj $Revision 1.6
* 2013/09/05 07:14:33 jomu $fixed ldap search if group setup is not complete.
* (1147451) $ $Revision 1.5 2013/09/04 15:07:26 jomu $fixed ldap search if
* group setup is not complete. (1147451) $$
*
*/