2014-01-11 4 views
2

Я настроил сервер OpenLDAP с этой конфигурацией:Аутентифицировать пользователя в сервере LDAP

version: 1 

# Entry 1: dc=unixmen,dc=com 
dn: dc=unixmen,dc=com 
dc: unixmen 
o: unixmen 
objectclass: top 
objectclass: dcObject 
objectclass: organization 

# Entry 2: cn=ServerAdmins,dc=unixmen,dc=com 
dn: cn=ServerAdmins,dc=unixmen,dc=com 
cn: ServerAdmins 
gidnumber: 501 
objectclass: posixGroup 
objectclass: top 

# Entry 3: cn=rcbandit,cn=ServerAdmins,dc=unixmen,dc=com 
dn: cn=rcbandit,cn=ServerAdmins,dc=unixmen,dc=com 
cn: rcbandit 
gidnumber: 501 
givenname: rcbandit 
homedirectory: /home/users/rcbandit 
objectclass: inetOrgPerson 
objectclass: posixAccount 
objectclass: top 
sn: rcbandit 
uid: rcbandit 
uidnumber: 1000 
userpassword: {MD5}2FeO34RYzgb7xbt2pYxcpA== 

И я создал этот Java код, который осуществляет поиск учетных данных:

public class SAuth 
{ 

    public static void main(String[] args) 
    { 

     Hashtable env = new Hashtable(11); 
     env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 
     env.put(Context.PROVIDER_URL, "ldap://192.168.1.177:389"); 
     //env.put(Context.SECURITY_AUTHENTICATION, "simple"); 
     //env.put(Context.SECURITY_PRINCIPAL, "cn=rcbandit,cn=ServerAdmins,dc=unixmen,dc=com"); 
     //env.put(Context.SECURITY_CREDENTIALS, "qwerty"); 

     // Enable connection pooling 
     env.put("com.sun.jndi.ldap.connect.pool", "true"); 

     try 
     { 
      LdapContext ctx = new InitialLdapContext(env, null); 
      ctx.setRequestControls(null); 
      NamingEnumeration<?> namingEnum = ctx.search("cn=rcbandit,cn=ServerAdmins,dc=unixmen,dc=com", "(objectclass=*)", getSimpleSearchControls()); 
      while (namingEnum.hasMore()) 
      { 
       SearchResult result = (SearchResult) namingEnum.next(); 
       Attributes attrs = result.getAttributes(); 
       System.out.println(attrs.get("cn")); 
       System.out.println(attrs.get("gidnumber")); 
       System.out.println(attrs.get("givenname")); 
       System.out.println(attrs.get("homedirectory")); 
       System.out.println(attrs.get("objectclass")); 
       System.out.println(attrs.get("objectclass")); 
       System.out.println(attrs.get("objectclass")); 
       System.out.println(attrs.get("sn")); 
       System.out.println(attrs.get("uid")); 
       System.out.println(attrs.get("uidnumber")); 
       System.out.println(attrs.get("userpassword")); 

      } 
      namingEnum.close(); 
      ctx.close(); 
     } 
     catch (NamingException e) 
     { 
      e.printStackTrace(); 
     } 

    } 

    private static SearchControls getSimpleSearchControls() 
    { 
     SearchControls searchControls = new SearchControls(); 
     searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); 
     searchControls.setTimeLimit(30000); 
     //String[] attrIDs = {"objectGUID"}; 
     //searchControls.setReturningAttributes(attrIDs); 
     return searchControls; 
    } 
} 

Когда я запускаю код я получаю этот результат :

cn: rcbandit 
gidNumber: 501 
givenName: rcbandit 
homeDirectory: /home/users/rcbandit 
objectClass: inetOrgPerson, posixAccount, top 
objectClass: inetOrgPerson, posixAccount, top 
objectClass: inetOrgPerson, posixAccount, top 
sn: rcbandit 
uid: rcbandit 
uidNumber: 1000 
null 

Каков правильный способ аутентификации имени пользователя и пароля?

ответ

1

Похоже, что вы можете получить информацию с помощью не прошедшего проверку подлинности соединения. Тем не менее вам необходимо выполнить операцию bind() в LDAP для выполнения аутентификации.

Функция операции Связывание заключается в разрешении обмена информацией аутентификации между клиентом и сервером. Операцию Bind следует рассматривать как операцию аутентификации.

Дополнительная информация here.

Операция связывания в вашем коде будет выполняться при создании InitialLdapContext. Тем не менее, вам необходимо иметь учетные данные, ответственные за безопасность, которые вы хотите аутентифицировать (которые вы закомментировали). В настоящее время вы читаете разрешенную информацию через неавторизованный канал.

Правильный способ заключается в связывании с использованием экземпляра InitialLdapContext с принципалом и учетными данными, которые вы хотите аутентифицировать и поймать javax.naming.AuthenticationException для неудавшихся.

env.put(Context.PROVIDER_URL, "ldap://XXX.XXX.XXX.XXX:XXX"); 
env.put(Context.SECURITY_AUTHENTICATION, "simple"); 
env.put(Context.SECURITY_PRINCIPAL, "cn=rcbandit,cn=ServerAdmins,dc=unixmen,dc=com"); 
env.put(Context.SECURITY_CREDENTIALS, "xxxx"); 
.. 
LdapContext ctx = new InitialLdapContext(env, null); 

} 
catch(AuthenticationException ex) { 
... 
} 
+1

Там находится одна проблема, я хочу использовать одно соединение, которое будет использоваться для аутентифицировать всех пользователей. Не могли бы вы изменить мой код, как он может быть исправлен? –

+0

@PeterPenzov Это интересное требование, и я не могу придумать, каким образом среда может разрешить это по умолчанию, если вы не предоставите некоторые особенности вокруг них. – PopoFibo

+0

Вы имеете в виду, что мне нужно настроить что-то еще на сервер LDAP? –

1

Это было бы легко сделать, если бы вы не использовали JNDI. Все SDK Java LDAP позволяют привязывать метод к одному и тому же соединению LDAP. Я бы настоятельно рекомендовал вам использовать современный, текущий LDAP SDK и НЕ использовать JNDI. В настоящее время нам нравится https://www.unboundid.com/products/ldap-sdk/.

Почему одно соединение? - Не требуется настройка на сервере LDAP.

Вот пример, который использует администратора для поиска, а затем связать в качестве возвращаемого записи:

package com.willeke.samples.ldap.jndi; 

import java.util.*; 

import javax.naming.*; 
import javax.naming.directory.*; 

/** 
* 
* <p> 
* Title: BasicJNDISearch 
* </p> 
* 
* <p> 
* Description: Provides a sample for performing JNDI Searches 
* </p> 
* 
* @author Jim Willeke 
* @version 1.0 
*/ 
public class BasicAdminSearchBind 
{ 
    public BasicAdminSearchBind(String[] args) 
    { 
    super(); 

    try 
    { 
     BasicAdminSearchBind.doBasicSearch(args); 
    } 
    catch (Exception ex) 
    { 
     ex.printStackTrace(); 
    } 
    } 

    /** 
    * 
    * @param stid 
    *   String - Standard ID (uid) 
    * @throws Exception 
    *    - 
    */ 
    public static void doBasicSearch(String[] args) throws Exception 
    { 
    System.out.println("Performing LDAP Search with:"); 
    System.out.println(" ldapHostName = " + args[0]); 
    System.out.println("  ldapPort = " + args[1]); 
    System.out.println("   bindDn = " + args[2]); 
    System.out.println("  bindDnPwd = " + args[3]); 
    System.out.println("  searchBase = " + args[4]); 
    System.out.println("   filter = (" + args[5] + "=" + args[6] + ")"); 
    System.out.println("   Scope: = SUBTREE_SCOPE"); 
    // Get the context for the admin account 
    DirContext adminCtx = getDirContext(args[0], args[1], args[2], args[3]); 
    SearchControls constraints = new SearchControls(); 
    // Set the Scope of the search 
    constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); 
    // Create the filter from args 
    String filter = "(" + args[5] + "=" + args[6] + ")"; 
    // Search for objects with those matching attributes 
    NamingEnumeration<?> answer = adminCtx.search(args[4], filter, constraints); 
    //formatResults(answer); 
    SearchResult sr = (SearchResult) answer.next(); 
    String userDN = sr.getNameInNamespace(); 
    //bind as returned entry 
    try 
    { 
     DirContext userCtx = bindAsEntry(args[0], args[1], userDN, "Secret Password"); 
     System.out.println("We are now bound as the User: "+ userDN); 
     // we could do something with the userCtx here. 
     userCtx.close(); 
    } 
    catch (Exception e) 
    { 
     System.err.println("We failed to make a bind as " + userDN + "\n" + e.getMessage()); 
    } 
    adminCtx.close(); 
    } 

    /** 
    * 
    * @param ldapHostName 
    * @param ldapPost 
    * @param bindDn 
    * @param bindDnPwd 
    * @return 
    * @throws NamingException 
    * @throws Exception 
    */ 
    private static DirContext bindAsEntry(String ldapHostName, String ldapPost, String bindDn, String bindDnPwd) throws NamingException 
    { 
    Hashtable<String, String> env = new Hashtable<String, String>(11); 
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 
    env.put(Context.PROVIDER_URL, "ldap://" + ldapHostName + ":" + ldapPost); 
    env.put(Context.SECURITY_PRINCIPAL, bindDn); 
    env.put(Context.SECURITY_CREDENTIALS, bindDnPwd); 
    // Create the initial context 
    DirContext ctx = new InitialDirContext(env); 
    return ctx; 
    } 

    /** 
    * Generic method to obtain a reference to a DirContext 
    * 
    * @param ldapHostName 
    * @param ldapPost 
    * @param bindDn 
    * @param bindDnPwd 
    */ 
    public static DirContext getDirContext(String ldapHostName, String ldapPost, String bindDn, String bindDnPwd) throws Exception 
    { 
    Hashtable<String, String> env = new Hashtable<String, String>(11); 
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 
    env.put(Context.PROVIDER_URL, "ldap://" + ldapHostName + ":" + ldapPost); 
    env.put(Context.SECURITY_PRINCIPAL, bindDn); 
    env.put(Context.SECURITY_CREDENTIALS, bindDnPwd); 
    // Create the initial context 
    DirContext ctx = new InitialDirContext(env); 
    return ctx; 
    } 

    /* 
    * Generic method to format the NamingEnumeration returned from a search. 
    */ 
    public static void formatResults(NamingEnumeration<?> enumer) throws Exception 
    { 
    int count = 0; 
    try 
    { 
     while (enumer.hasMore()) 
     { 
     SearchResult sr = (SearchResult) enumer.next(); 
     System.out.println("SEARCH RESULT:" + sr.getName()); 
     formatAttributes(sr.getAttributes()); 
     System.out.println("===================================================="); 
     count++; 
     } 
     System.out.println("Search returned " + count + " results"); 
    } 
    catch (NamingException e) 
    { 
     e.printStackTrace(); 
    } 
    } 

    /* 
    * Generic method to format the Attributes .Displays all the multiple values of each Attribute in the Attributes 
    */ 
    public static void formatAttributes(Attributes attrs) throws Exception 
    { 
    if (attrs == null) 
    { 
     System.out.println("This result has no attributes"); 
    } 
    else 
    { 
     try 
     { 
     for (NamingEnumeration<?> enumer = attrs.getAll(); enumer.hasMore();) 
     { 
      Attribute attrib = (Attribute) enumer.next(); 

      System.out.println("ATTRIBUTE :" + attrib.getID()); 
      for (NamingEnumeration<?> e = attrib.getAll(); e.hasMore();) 
      { 
      Object value = e.next(); 
      boolean canPrint = isAsciiPrintable(value); 
      if (canPrint) 
      { 
       System.out.println("\t\t  = " + value); 
      } 
      else 
      { 
       System.out.println("\t\t  = <-value is not printable->"); 
      } 
      } 
     } 
     } 
     catch (NamingException e) 
     { 
     e.printStackTrace(); 
     } 
    } 
    } 

    /** 
    * Check to see if this Object can be printed. 
    * 
    * @param obj 
    * @return 
    */ 
    public static boolean isAsciiPrintable(Object obj) 
    { 
    String str = null; 
    try 
    { 
     str = (String) obj; 
    } 
    catch (Exception e) 
    { 
     return false; 
     // TODO Auto-generated catch block e.printStackTrace(); 
    } 
    if (str == null) 
    { 
     return false; 
    } 
    int sz = str.length(); 
    for (int i = 0; i < sz; i++) 
    { 
     if (isAsciiPrintable(str.charAt(i)) == false) 
     { 
     return false; 
     } 
    } 
    return true; 
    } 

    /** 
    * Used by isAsciiPrintable(Object obj) 
    * 
    * @param ch 
    * @return 
    */ 
    public static boolean isAsciiPrintable(char ch) 
    { 
    return ch >= 32 && ch < 127; 
    } 

    /** 
    * Does a simple search on the LDAP Directory 
    * 
    * String ldapHostName = args[0]; String ldapPort = args[1]; String bindDn = args[2]; String bindDnPwd = args[3]; String searchBase = args[4]; // String searchScope=args[4]; String searchAttribute = args[5]; 
    * String searchAttributeValue = args[6]; 
    * 
    * @param args 
    * 
    */ 
    public static void main(String[] args) 
    { 
    if (args.length == 7) 
    { 
     BasicAdminSearchBind basicjndisearch = new BasicAdminSearchBind(args); 
    } 
    else 
    { 
     System.out.println("\nYou must provide ldapHostName, ldapPort, bindDn, bindDnPwd, searchBase, searchAttribute and searchAttributeValue on the command line!\n"); 
    } 
    } 
} 

-Джим

Смежные вопросы