我使用此配置配置了OpenLDAP服务器:
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
验证用户名和密码的正确方法是什么?
答案 0 :(得分:1)
看起来您可以通过未经身份验证的连接获取信息。但是,您需要在LDAP中执行bind()
操作才能执行身份验证。
Bind操作的功能是允许在客户端和服务器之间交换认证信息。绑定操作应该被认为是&#34;验证&#34;操作
更多信息here。
创建InitialLdapContext
时,将执行代码中的绑定操作。但是,您需要具有要进行身份验证的凭据,安全主体(已注释掉)。目前,您正在通过未经身份验证的渠道阅读可用的信息。
正确的方法是使用实例化InitialLdapContext
与要验证的主体和凭据绑定,并为失败的javax.naming.AuthenticationException
捕获。{/ p>
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 :(得分:1)
如果您不使用JNDI,这很容易做到。所有Java LDAP SDK都允许方法通过同一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");
}
}
}
-Jim