Java ldaps active directory

Querying Active Directory using Java

I had written a blog post about Querying Active Directory using C# it’s simple and easy to understand then I thought to provide similar approach/article Querying Active Directory using Java. This article is all about how to achieve Querying Active Directory using Java.

I will take you through below elements in detail-

  • Retrieve User Details or an Object from AD based on Username – sAMAccountName
  • Retrieve User Details or an Object from AD based on user Email ID – mail

To know more about filters, attributes/properties you can use for active directory query.

Required Details

  • LDAP address (For e.g.: myjeeva.com or IP of the Domain Controller/Global Catalog[GC])
  • Port # (For e.g.: 3289 or 389) where would you to like search user details?
  • Domain Username
  • Domain Password

Important Reference: will introduce you to the classes needed for querying Active Directory using Java. Have a look and know more about it.

How to do – Step by Step explaination

For an easy understanding perspective; I will be following line by line approach. ActiveDirectory Class file and example of how to use that ActiveDirectory class file in java program. Downloads of these files you will find below.

Step 1

Compose LDAP address and supply following parameters username, password, ldap address as a domain into ActiveDirectory constructor.

Invoke searchUser method with parameters of searchTerm, choice and searchBase.

Источник

2 способа настройки аутентификации LDAP Active Directory в учебном примере по безопасности Java Spring

Аутентификация LDAP является одним из самых популярных в мире механизмов аутентификации для корпоративных приложений, а Active Directory (реализация LDAP от Microsoft для Windows) – еще один широко используемый сервер LDAP. Во многих проектах нам необходимо проходить аутентификацию в активном каталоге с использованием LDAP по учетным данным, указанным на экране входа в систему. Иногда эта простая задача усложняется из-за различных проблем, возникающих при реализации и интеграции, и из-за отсутствия стандартного способа аутентификации LDAP . Java обеспечивает поддержку LDAP, но в этой статье я в основном буду говорить о весенней безопасности, потому что это моя любимая среда Java для аутентификации, авторизации и безопасности.

Мы можем сделать то же самое в Java, написав собственную программу для поиска LDAP, а затем связывание LDAP, но, как я сказал, это намного проще и чище, когда вы используете Spring Security для аутентификации LDAP.

Наряду с поддержкой LDAP Spring Security также предоставляет несколько других функций, которые требуются корпоративному Java-приложению, включая SSL-безопасность, шифрование паролей и средства ожидания сеанса.

1. Основы аутентификации LDAP

Прежде чем углубляться в аутентификацию LDAP в Active Directory, давайте познакомимся с некоторыми терминами LDAP, потому что большую часть времени пользователи делают это в первый раз, и они не очень знакомы с типичными глоссариями LDAP, такими как Dn, Ou, Bind или search и т. Д.
Dn – Отличительное имя , уникальное имя, которое используется для поиска пользователя на сервере LDAP, например, Microsoft Active Directory.
Ou – организационная единица
Привязка – LDAP Привязка – это операция, при которой клиенты LDAP отправляют bindRequest пользователю LDAP, включая имя пользователя и пароль, и, если сервер LDAP может найти правильные имя пользователя и пароль, он разрешает доступ к серверу LDAP.
Поиск – поиск LDAP – это операция, которая выполняется для получения Dn пользователя с использованием некоторых учетных данных пользователя.
Root – верхний элемент каталога LDAP, такой как Root of a tree.
BaseDn – ветвь в дереве LDAP, которая может использоваться в качестве базы для операции поиска LDAP, например, dc = Microsoft, dc = org ”

Читайте также:  Обработка данных php скриптом

Если вы хотите узнать больше о LDAP, проверьте эту ссылку, там есть подробная информация о LDAP.

2. Аутентификация LDAP в Active Directory Spring Security

Существует два способа реализации аутентификации в активном каталоге с использованием протокола LDAP в Spring Spring. Первый способ – это программный и декларативный способ, который требует некоторого кодирования и некоторой конфигурации.

С другой стороны, второй способ – это готовое решение от ActireDirectoryAuthenticationProvider Security, которое просто требует настройки ActireDirectoryAuthenticationProvider и все готово. мы увидим оба подхода, но я предлагаю использовать второй, потому что он прост и удобен в использовании.

2.1 Аутентификация в Active Directory с использованием LDAP в Spring Security – пример 1

конфигурация
Добавьте следующую конфигурацию в ваш весенний файл application-context.xml, я бы предложил поместить эту конфигурацию в отдельный файл application-context-security.XML вместе с другими элементами, связанными с безопасностью.
1) Настройка сервера LDAP
Чтобы настроить сервер LDAP, поместите следующий фрагмент XML в файл конфигурации безопасности Spring:

Источник

How To Authenticate Users With Active Directory

I recently needed to write an app to authenticate users via Active Directory. For this, I used the native LDAP classes in Java and rolled my own «ActiveDirectory» class. The class provides several static methods used to authenticate users and change passwords.

Authentication Example

Here’s a really simple example of how to authenticate a user using a username and password. The ActiveDirectory class actually provides 3 different getConnection() methods for for authenticating users.

Change Password

In addition to authenticating users, the ActiveDirectory class can be used to change a user’s password. Here’s an example:

Note that there are several possible errors that you may encounter when changing a password. For starters, the Active Directory server must be LDAPS enabled. Secondly, the new password must meet certain requirements (e.g. password complexity, length, minimum password age, password history, etc.). Unfortunately, the Java/LDAP API doesn’t tell you exactly what’s wrong. It simply spits out a generic error:

LDAP: error code 19 - 0000052D: AtrErr: DSID-03190F00, #1: 0: 0000052D: DSID-03190F00, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 9005a (unicodePwd)

If you are a domain administrator, you can view/update the password requirements on the Active Directory server via Administrative Tools->Domain Securitty Policy->Account Policies->Password Policy

Читайте также:  Typescript sort string array

The one policy that bit me in the ass when developing/testing the change password feature was the Minimum Password Age. For testing purposes, I changed the setting on my domain controller from «Undefined» to «0». After changing this, or any other password policy, remember to refresh the domain controller by running «gpupdate»:

ActiveDirectory Class

Here’s the source code for the ActiveDirectory Class. This is a standalone class and does not have any 3rd party dependencies.

package javaxt.security; import java.util.Hashtable; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import static javax.naming.directory.SearchControls.SUBTREE_SCOPE; import javax.naming.ldap.LdapContext; import javax.naming.ldap.InitialLdapContext; //Imports for changing password import javax.naming.directory.ModificationItem; import javax.naming.directory.BasicAttribute; import javax.naming.ldap.StartTlsResponse; import javax.naming.ldap.StartTlsRequest; import javax.net.ssl.*; //****************************************************************************** //** ActiveDirectory //*****************************************************************************/ /** * Provides static methods to authenticate users, change passwords, etc. * ******************************************************************************/ public class ActiveDirectory < private static String[] userAttributes = < "distinguishedName","cn","name","uid", "sn","givenname","memberOf","samaccountname", "userPrincipalName" >; private ActiveDirectory()<> //************************************************************************** //** getConnection //*************************************************************************/ /** Used to authenticate a user given a username/password. Domain name is * derived from the fully qualified domain name of the host machine. */ public static LdapContext getConnection(String username, String password) throws NamingException < return getConnection(username, password, null, null); >//************************************************************************** //** getConnection //*************************************************************************/ /** Used to authenticate a user given a username/password and domain name. */ public static LdapContext getConnection(String username, String password, String domainName) throws NamingException < return getConnection(username, password, domainName, null); >//************************************************************************** //** getConnection //*************************************************************************/ /** Used to authenticate a user given a username/password and domain name. * Provides an option to identify a specific a Active Directory server. */ public static LdapContext getConnection(String username, String password, String domainName, String serverName) throws NamingException < if (domainName==null)< try< String fqdn = java.net.InetAddress.getLocalHost().getCanonicalHostName(); if (fqdn.split("\\.").length>1) domainName = fqdn.substring(fqdn.indexOf(".")+1); > catch(java.net.UnknownHostException e)<> > //System.out.println("Authenticating " + username + "@" + domainName + " through " + serverName); if (password!=null) < password = password.trim(); if (password.length()==0) password = null; >//bind by using the specified username/password Hashtable props = new Hashtable(); String principalName = username + "@" + domainName; props.put(Context.SECURITY_PRINCIPAL, principalName); if (password!=null) props.put(Context.SECURITY_CREDENTIALS, password); String ldapURL = "ldap://" + ((serverName==null)? domainName : serverName + "." + domainName) + '/'; props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); props.put(Context.PROVIDER_URL, ldapURL); try < return new InitialLdapContext(props, null); >catch(javax.naming.CommunicationException e) < throw new NamingException("Failed to connect to " + domainName + ((serverName==null)? "" : " through " + serverName)); >catch(NamingException e) < throw new NamingException("Failed to authenticate " + username + "@" + domainName + ((serverName==null)? "" : " through " + serverName)); >> //************************************************************************** //** getUser //*************************************************************************/ /** Used to check whether a username is valid. * @param username A username to validate (e.g. "peter", "peter@acme.com", * or "ACME\peter"). */ public static User getUser(String username, LdapContext context) < try< String domainName = null; if (username.contains("@"))< username = username.substring(0, username.indexOf("@")); domainName = username.substring(username.indexOf("@")+1); >else if(username.contains("\\")) < username = username.substring(0, username.indexOf("\\")); domainName = username.substring(username.indexOf("\\")+1); >else < String authenticatedUser = (String) context.getEnvironment().get(Context.SECURITY_PRINCIPAL); if (authenticatedUser.contains("@"))< domainName = authenticatedUser.substring(authenticatedUser.indexOf("@")+1); >> if (domainName!=null) < String principalName = username + "@" + domainName; SearchControls controls = new SearchControls(); controls.setSearchScope(SUBTREE_SCOPE); controls.setReturningAttributes(userAttributes); NamingEnumerationanswer = context.search( toDC(domainName), "(& (userPrincipalName="+principalName+")(objectClass=user))", controls); if (answer.hasMore()) < Attributes attr = answer.next().getAttributes(); Attribute user = attr.get("userPrincipalName"); if (user!=null) return new User(attr); >> > catch(NamingException e) < //e.printStackTrace(); >return null; > //************************************************************************** //** getUsers //*************************************************************************/ /** Returns a list of users in the domain. */ public static User[] getUsers(LdapContext context) throws NamingException < java.util.ArrayListusers = new java.util.ArrayList(); String authenticatedUser = (String) context.getEnvironment().get(Context.SECURITY_PRINCIPAL); if (authenticatedUser.contains("@")) < String domainName = authenticatedUser.substring(authenticatedUser.indexOf("@")+1); SearchControls controls = new SearchControls(); controls.setSearchScope(SUBTREE_SCOPE); controls.setReturningAttributes(userAttributes); NamingEnumeration answer = context.search( toDC(domainName), "(objectClass=user)", controls); try< while(answer.hasMore()) < Attributes attr = ((SearchResult) answer.next()).getAttributes(); Attribute user = attr.get("userPrincipalName"); if (user!=null)< users.add(new User(attr)); >> > catch(Exception e)<> > return users.toArray(new User[users.size()]); > private static String toDC(String domainName) < StringBuilder buf = new StringBuilder(); for (String token : domainName.split("\\.")) < if(token.length()==0) continue; // defensive check if(buf.length()>0) buf.append(","); buf.append("DC=").append(token); > return buf.toString(); > //************************************************************************** //** User Class //*************************************************************************/ /** Used to represent a User in Active Directory */ public static class User < private String distinguishedName; private String userPrincipal; private String commonName; public User(Attributes attr) throws javax.naming.NamingException < userPrincipal = (String) attr.get("userPrincipalName").get(); commonName = (String) attr.get("cn").get(); distinguishedName = (String) attr.get("distinguishedName").get(); >public String getUserPrincipal() < return userPrincipal; >public String getCommonName() < return commonName; >public String getDistinguishedName() < return distinguishedName; >public String toString() < return getDistinguishedName(); >/** Used to change the user password. Throws an IOException if the Domain * Controller is not LDAPS enabled. * @param trustAllCerts If true, bypasses all certificate and host name * validation. If false, ensure that the LDAPS certificate has been * imported into a trust store and sourced before calling this method. * Example: String keystore = "/usr/java/jdk1.5.0_01/jre/lib/security/cacerts"; System.setProperty("javax.net.ssl.trustStore",keystore); */ public void changePassword(String oldPass, String newPass, boolean trustAllCerts, LdapContext context) throws java.io.IOException, NamingException < String dn = getDistinguishedName(); //Switch to SSL/TLS StartTlsResponse tls = null; try< tls = (StartTlsResponse) context.extendedOperation(new StartTlsRequest()); >catch(Exception e) < //"Problem creating object: javax.naming.ServiceUnavailableException: [LDAP: error code 52 - 00000000: LdapErr: DSID-0C090E09, comment: Error initializing SSL/TLS, data 0, v1db0" throw new java.io.IOException("Failed to establish SSL connection to the Domain Controller. Is LDAPS enabled?"); >//Exchange certificates if (trustAllCerts) < tls.setHostnameVerifier(DO_NOT_VERIFY); SSLSocketFactory sf = null; try < SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, TRUST_ALL_CERTS, null); sf = sc.getSocketFactory(); >catch(java.security.NoSuchAlgorithmException e) <> catch(java.security.KeyManagementException e) <> tls.negotiate(sf); > else < tls.negotiate(); >//Change password try < //ModificationItem[] modificationItems = new ModificationItem[1]; //modificationItems[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodePwd", getPassword(newPass))); ModificationItem[] modificationItems = new ModificationItem[2]; modificationItems[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, new BasicAttribute("unicodePwd", getPassword(oldPass)) ); modificationItems[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("unicodePwd", getPassword(newPass)) ); context.modifyAttributes(dn, modificationItems); >catch(javax.naming.directory.InvalidAttributeValueException e) < String error = e.getMessage().trim(); if (error.startsWith("[") && error.endsWith("]"))< error = error.substring(1, error.length()-1); >System.err.println(error); //e.printStackTrace(); tls.close(); throw new NamingException( "New password does not meet Active Directory requirements. " + "Please ensure that the new password meets password complexity, " + "length, minimum password age, and password history requirements." ); > catch(NamingException e) < tls.close(); throw e; >//Close the TLS/SSL session tls.close(); > private static final HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() < public boolean verify(String hostname, SSLSession session) < return true; >>; private static TrustManager[] TRUST_ALL_CERTS = new TrustManager[] < new X509TrustManager() < public java.security.cert.X509Certificate[] getAcceptedIssuers() < return null; >public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) < >public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) < >> >; private byte[] getPassword(String newPass)< String quotedPassword = "\"" + newPass + "\""; //return quotedPassword.getBytes("UTF-16LE"); char unicodePwd[] = quotedPassword.toCharArray(); byte pwdArray[] = new byte[unicodePwd.length * 2]; for (int i=0; i>> 8); pwdArray[i*2 + 0] = (byte) (unicodePwd[i] & 0xff); > return pwdArray; > > >

Acknowledgment

Источник

Оцените статью