LDAP

JAVA與LDAP查詢

朱文吉 2021/09/10 18:09:20
74

1.前言

    有時在客戶端已有LDAP,帳密的驗證需使用LDAP,可參考如何驗證成功來完成登入,以及會介紹如何查詢資料

2.驗證成功

    2.1.程式碼,大部份的驗證就使用該方式就行了,範例是以admin來驗證登入LDAP,這是可以使用一般帳號來做驗證,並非只有admin

import java.util.Hashtable;

import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

public class T1 {

	public static void main(String[] args) {
		T1 t1 = new T1();
		//使用admin帳號驗證,也可以使用一般帳號驗證
		t1.connect("ldap://127.0.0.1:389", "uid=admin,dc=kstpi,dc=com", "123123");
	}

	public void connect(String url,String username,String password) {
		DirContext ctx=null;
		Hashtable<String,String> HashEnv = new Hashtable<String,String>();
		HashEnv.put(Context.SECURITY_AUTHENTICATION, "simple"); // LDAP訪問安全級別(none,simple,strong)
		HashEnv.put(Context.SECURITY_PRINCIPAL, username); //使用者名稱
		HashEnv.put(Context.SECURITY_CREDENTIALS, password); //密碼
		HashEnv.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
		HashEnv.put("com.sun.jndi.ldap.connect.timeout", "3000");//連線超時設定為3秒
		HashEnv.put(Context.PROVIDER_URL, url);// 
		try {
			ctx = new InitialDirContext(HashEnv);
			System.out.println("驗證成功!");
		} catch (AuthenticationException e) {
			System.out.println("驗證失敗!");
			e.printStackTrace();
		} catch (javax.naming.CommunicationException e) {
			System.out.println("連線失敗!");
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			if(null!=ctx){
				try {
					ctx.close();
					ctx=null;
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
}

    2.2.執行結果

驗證成功!

3.假設資料內容如下,XX.ldif

dn: dc=kstpi,dc=com
objectClass: top
objectClass: domain

dn: ou=people,dc=kstpi,dc=com
objectclass: top
objectclass: organizationalUnit
ou: people

dn: uid=ben,ou=people,dc=kstpi,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: didi
sn: ben
uid: didi
userPassword: 123123

dn: uid=bob,ou=people,dc=kstpi,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Bob Hamilton
sn: bob
uid: bob
userPassword: 321321

4.查詢資料

    4.1.程式碼

import java.util.Hashtable;

import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

public class T1 {

	public static void main(String[] args) {
		T1 t1 = new T1();
		//使用admin帳號驗證,也可以使用一般帳號驗證
		t1.connect("ldap://127.0.0.1:389", "uid=admin,dc=kstpi,dc=com", "123123");
	}

	public void connect(String url,String username,String password) {
		DirContext ctx=null;
		Hashtable<String,String> HashEnv = new Hashtable<String,String>();
		HashEnv.put(Context.SECURITY_AUTHENTICATION, "simple"); // LDAP訪問安全級別(none,simple,strong)
		HashEnv.put(Context.SECURITY_PRINCIPAL, username); //使用者名稱
		HashEnv.put(Context.SECURITY_CREDENTIALS, password); //密碼
		HashEnv.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
		HashEnv.put("com.sun.jndi.ldap.connect.timeout", "3000");//連線超時設定為3秒
		HashEnv.put(Context.PROVIDER_URL, url);// 
		try {
			ctx = new InitialDirContext(HashEnv);
			System.out.println("驗證成功!");
			
			String dnBase="uid=ben,ou=people,dc=kstpi,dc=com";
			Attributes attrs = ctx.getAttributes(dnBase);
			System.out.println("cn" + ":" + attrs.get("cn").get());
			System.out.println("sn" + ":" + attrs.get("sn").get());
			
		} catch (AuthenticationException e) {
			System.out.println("驗證失敗!");
			e.printStackTrace();
		} catch (javax.naming.CommunicationException e) {
			System.out.println("連線失敗!");
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			if(null!=ctx){
				try {
					ctx.close();
					ctx=null;
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
}

    4.2.執行結果

驗證成功!
cn:didi
sn:ben

5.使用search查資料

    5.1.程式碼,第1個參數是dnBase,第2個參數是filter,第3個是搜尋的設定

import java.util.Hashtable;

import javax.naming.AuthenticationException;
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.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

public class T1 {

	public static void main(String[] args) {
		T1 t1 = new T1();
		//使用admin帳號驗證,也可以使用一般帳號驗證
		t1.connect("ldap://127.0.0.1:389", "uid=admin,dc=kstpi,dc=com", "123123");
	}

	public void connect(String url,String username,String password) {
		DirContext ctx=null;
		Hashtable<String,String> HashEnv = new Hashtable<String,String>();
		HashEnv.put(Context.SECURITY_AUTHENTICATION, "simple"); // LDAP訪問安全級別(none,simple,strong)
		HashEnv.put(Context.SECURITY_PRINCIPAL, username); //使用者名稱
		HashEnv.put(Context.SECURITY_CREDENTIALS, password); //密碼
		HashEnv.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
		HashEnv.put("com.sun.jndi.ldap.connect.timeout", "3000");//連線超時設定為3秒
		HashEnv.put(Context.PROVIDER_URL, url);
		
		NamingEnumeration<?> namingEnum = null;
		try {
			ctx = new InitialDirContext(HashEnv);
			System.out.println("驗證成功!");
			
			String dnBase="uid=ben,ou=people,dc=kstpi,dc=com";
			namingEnum = ctx.search(dnBase, "objectclass=person", getSearchControls());
			while (namingEnum.hasMore ()) {
		        SearchResult result = (SearchResult) namingEnum.next();    
		        Attributes attrs = result.getAttributes ();
			    String cn = getAttributeValue(attrs.get("cn"));
			    String sn = getAttributeValue(attrs.get("sn"));
			    String userPassword = getAttributeValue(attrs.get("userPassword"));
			    System.out.println("cn" + ":" + cn);
			    System.out.println("sn" + ":" + sn);
			    System.out.println("userPassword" + ":" + userPassword);
			}
		} catch (AuthenticationException e) {
			System.out.println("驗證失敗!");
			e.printStackTrace();
		} catch (javax.naming.CommunicationException e) {
			System.out.println("連線失敗!");
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			if(null!=ctx){
				try {
					ctx.close();
					ctx=null;
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if(null!=namingEnum){
				try {
					namingEnum.close();
					namingEnum=null;
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private String getAttributeValue(Attribute attr) throws NamingException {
		String val = null;
		if(attr != null) {
			Object obj = attr.get();
			if(obj instanceof byte[]) {
				val = new String((byte[]) obj);
			}else {
				val = obj.toString();
			}
		}
		return val;
	}

	private SearchControls getSearchControls() {
	    SearchControls searchControls = new SearchControls();
	    searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
	    searchControls.setTimeLimit(30000);
	    return searchControls;
	}
}

    5.2.執行結果

驗證成功!
cn:didi
sn:ben
userPassword:123123

6.filter多條件

    6.1.多條件可參考https://www.796t.com/post/NThmZmM=.html

    6.2.若將上一個範例修改dnBase為String dnBase="dc=kstpi,dc=com";會得以下的結果

驗證成功!
cn:didi
sn:ben
userPassword:123123
cn:Bob Hamilton
sn:bob
userPassword:321321

    6.3.多條件程式碼(objectclass為person和uid為ben)

			String dnBase="dc=kstpi,dc=com";
			namingEnum = ctx.search(dnBase, "(&(objectclass=person)(uid=ben))", getSearchControls());
			while (namingEnum.hasMore ()) {
		        SearchResult result = (SearchResult) namingEnum.next();    
		        Attributes attrs = result.getAttributes ();
			    String cn = getAttributeValue(attrs.get("cn"));
			    String sn = getAttributeValue(attrs.get("sn"));
			    String userPassword = getAttributeValue(attrs.get("userPassword"));
			    System.out.println("cn" + ":" + cn);
			    System.out.println("sn" + ":" + sn);
			    System.out.println("userPassword" + ":" + userPassword);
			}

    6.4.執行結果

驗證成功!
cn:didi
sn:ben
userPassword:123123
朱文吉