什么是LDAP,百度百科一堆專業術語的描述。
我總結為一句話:輕量級目錄訪問協議,有數據庫的數據存儲功能,以樹狀層次型存儲方式,就好像你的電話薄那樣。
在一次項目中,由於該項目是教育性管理項目,客戶要求項目必須部署在內網。那么在內網的話,就代表用戶需要去撥VPN才能進行內網的訪問。
其實當時我想到的是,單獨開個注冊映射到外網,讓用戶自己注冊,管理員進行審核,然后用VPN去讀數據庫中的賬號和密碼就行了。這樣,我們的系統和vpn就
相當於統一賬號。但是當我確認需求的時候,那個老師告訴我們,他不會讀什么數據庫,他能夠LDAP或者windows域,當時我直接蒙逼了。沒聽過這個,最后花時間
看了下,發現也不是那么吊。切入正題
(1) 在官網上下載LDAP並安裝,注意兩點,1、第二步你輸入的密碼一定要記着,默認是secret;2、到“backend configuration” 這一步的時候,選擇“BDB”
其他的你就一直下一步。安裝完成的LDAP 默認是啟動。你不用管他
(2)找到你安裝的LDAP位置,找到“slapd.conf”這個配置文件。打開它。
里面有兩行默認的配置
suffix "dc=maxcrc,dc=com"
rootdn "cn=Manager,dc=maxcrc,dc=com"
這兩行東西其實是可以隨便改的。只要能和你接下來要導入的conf文件中的配置匹配就可以。
其實,上面的兩行屬性可以理解為用戶名和匹配項,用戶名:cn=manager,匹配項:dc=maxcrc,dc=com
(3)寫一個ynjy.conf文件
利用這個文件,你可以導入你的初始ldap的管理員
dn: uid=lrd,ou=People,dc=maxcrc,dc=com
uid: lrd
objectClass: inetOrgPerson
mail: 782122271@qq.com
userPassword: 123456
labeledURI: http://www.maxcrc.com
sn: Sun
cn: lrd Sun
上面的uid就類似於你的標示,ou=People,類似於你的電話薄名兒,里面存什么待會兒我們利用java來進行添加。
dc=maxcrc,dc=com 這句必須要和你的“slapd.conf”中的匹配,就是我上面說的匹配項。
注意點來了,LDAP可以自定義屬性,通過schema自定義,但初次不要去試,因為容易失敗,ldap的資料還是比較少。解決問題有時候摸不着頭緒
ldap提供了本身自帶的屬性,就是我們上的uid,mail,userPassword,labeledURI,sn,cn等,,記住,這幾個屬性必須不能改它。大小寫都認。不然導不進去。
(4)導入ynjy.conf進入ldap
cmd進入命令窗口,定位到你的ldap目錄中
輸入命令:ldapadd -x -D "cn=Manager,dc=maxcrc,dc=com" -w secret -f ynjy.ldif
你會看見執行條目成功的提示
你可以下載一個ldapBrowser進行查看。
上面的初步ldap平台的准備工作就完了
接下來,我們准備Java的訪問
其實和連接JDBC方式是一樣的。注意的就是LDAP的cn,dc這些屬性要匹配。相當於賬號!!!
我就直接將我的LDAPHelper代碼貼出來。並且附上一段簡單將數據讀進LDAP中的代碼
package util;
import java.util.Hashtable;
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
public class LDAPHelper {
private final String URL = "ldap://192.168.2.19:389/";
private final String BASEDN = "ou=People,dc=maxcrc,dc=com"; // 根據自己情況進行修改
private final String FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
private LdapContext ctx = null;
private final Control[] connCtls = null;
private void LDAP_connect() {
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
env.put(Context.PROVIDER_URL, URL + BASEDN);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
String root = "cn=Manager,dc=maxcrc,dc=com"; //根據自己情況修改
env.put(Context.SECURITY_PRINCIPAL, root); // 管理員
env.put(Context.SECURITY_CREDENTIALS, "daqsoft"); // 管理員密碼
try {
ctx = new InitialLdapContext(env, connCtls);
System.out.println( "連接成功" );
} catch (javax.naming.AuthenticationException e) {
System.out.println("連接失敗:");
e.printStackTrace();
} catch (Exception e) {
System.out.println("連接出錯:");
e.printStackTrace();
}
}
private void closeContext(){
if (ctx != null) {
try {
ctx.close();
}
catch (NamingException e) {
e.printStackTrace();
}
}
}
private String getUserDN(String uid) {
String userDN = "";
LDAP_connect();
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration<SearchResult> en = ctx.search("", "uid=" + uid, constraints);
if (en == null || !en.hasMoreElements()) {
System.out.println("未找到該用戶");
}
// maybe more than one element
while (en != null && en.hasMoreElements()) {
Object obj = en.nextElement();
if (obj instanceof SearchResult) {
SearchResult si = (SearchResult) obj;
userDN += si.getName();
userDN += "," + BASEDN;
} else {
System.out.println(obj);
}
}
} catch (Exception e) {
System.out.println("查找用戶時產生異常。");
e.printStackTrace();
}
return userDN;
}
public boolean authenricate(String UID, String password) {
boolean valide = false;
String userDN = getUserDN(UID);
try {
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
ctx.reconnect(connCtls);
System.out.println(userDN + " 驗證通過");
valide = true;
} catch (AuthenticationException e) {
System.out.println(userDN + " 驗證失敗");
System.out.println(e.toString());
valide = false;
} catch (NamingException e) {
System.out.println(userDN + " 驗證失敗");
valide = false;
}
closeContext();
return valide;
}
public boolean addUser(String usr, String pwd,String uid,String description) {
try {
LDAP_connect();
BasicAttributes attrsbu = new BasicAttributes();
BasicAttribute objclassSet = new BasicAttribute("objectclass");
objclassSet.add("inetOrgPerson");
attrsbu.put(objclassSet);
attrsbu.put("sn", usr);
attrsbu.put("cn", usr);
attrsbu.put("uid", uid);
attrsbu.put("userPassword", pwd);
attrsbu.put("description", description);
ctx.createSubcontext("uid="+uid+"", attrsbu);
return true;
} catch (NamingException ex) {
ex.printStackTrace();
}
closeContext();
return false;
}
//測試
public static void main(String[] args) {
LDAPHelper ldap = new LDAPHelper();
//ldap.LDAP_connect();
if(ldap.authenricate("yorker", "daqsoft") == true){
System.out.println( "該用戶認證成功" );
}
//ldap.addUser("yorker","secret");
}
}
上面的代碼是我從另外一張表獲得的用戶信息寫進了ldap。
ldap的操作就介紹完畢。有問題的大家可以一起討論。我也是剛用到將這個東西勉強用起來