安装:
https://www.cnblogs.com/lemon-le/p/6266921.html
安装完不能添加用户:
http://www.live-in.org/archives/1731.html
ladp:只需要知道是一种协议,以目录的形式(结构树)来管理资原(用户、用户组、地址簿、邮件用户等)。
一些大公司会选择以LDAP来存储用户及其信息。
所以就像是数据库一般,LDAP也是有client端和server端。server端是用来存放资源,client端用来操作增删改查等操作。
Objectclass
LDAP对象类,是LDAP内置的数据模型。每种objectClass有自己的数据结构,比如我们有一种叫“电话薄”的objectClass,肯定会内置很多属性(attributes),如姓名(uid),身份证号(uidNumber),单位名称(gid),家庭地址(homeDirectory)等,同时,还有一种叫“同学录”的objectClass,具备“电话薄”里的一些attributes(如uid、homeDirectory),还会具有“电话薄”没有的attributes(如description等)。
objectClass可分为以下3类:
结构型(Structural) :如person和organizationUnit;
辅助型(Auxiliary) :如extensibeObject;
抽象型(Abstract) :如top,抽象型的objectClass不能直接使用。
在OpenLDAP的schema中定义了很多objectClass,下面列出部分常用的objectClass的名称。
● account
● alias
● dcobject
● domain
● ipHost
● organization
● organizationalRole
● organizationalUnit
● person
● organizationalPerson
● inetOrgPerson
● residentialPerson
● posixAccount
● posixGroup
属性:
●dn 唯一标识 用户登陆ldap的账号
● c:国家。
● cn:common name,指一个对象的名字。如果指人,需要使用其全名。
● dc:domain Component,常用来指一个域名的一部分。
● givenName:指一个人的名字,不能用来指姓。
● l:指一个地名,如一个城市或者其他地理区域的名字。
● mail:电子信箱地址。
● o:organizationName,指一个组织的名字。
● ou:organizationalUnitName,指一个组织单元的名字。
● sn:surname,指一个人的姓。
● telephoneNumber:电话号码,应该带有所在的国家的代码。
● uid:User Name,通常指某个用户的登录名,与Linux系统中用户的uid不同。账号(第三方应用)
● gidNumber:为GroupId,即组ID,用来标识用户组的唯一标识符
● uidNumber 身份证号
下面列出部分常用objectClass要求必设的属性:
● account:userid。
● organization:o。
● person:cn和sn。
● organizationalPerson:与person相同。
● organizationalRole:cn。
● organizationUnit:ou。
● posixGroup:cn、gidNumber。
● posixAccount:cn、gidNumber、homeDirectory、uid、uidNumber。
import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.*;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import java.util.Hashtable;
import java.util.Vector;
public class test {
private final String URL = "ldap://39.xxx.xx.xx:389/"; // 根据自己情况进行修改
private final String BASEDN = "dc=ldap,dc=tydic,dc=org"; // 根据自己情况进行修改,根目录
private final String FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
private LdapContext ctx = null;
private final Control[] connCtls = null;
public static void main(String[] args) throws Exception {
test ldap = new test();
//连接ldap
ldap.LDAP_connect();
//查询节点
// System.out.println(ldap.getUserOrUserGroup("ljp"));
//遍历节点
// base :根节点(在这里是"dc=example,dc=com")
// scope :搜索范围,分为"base"(本节点),"one"(单层),""(全部节点遍历)
// filter :指定子节点(格式为"(objectclass=*)",*是指全部,你也可以指定某一特定类型的树节点)
// ldap.searchInformation(ldap.BASEDN,"base","(objectClass=*)");
//添加组
// System.out.println(ldap.addUserGroup("harvey","posixGroup"));
// System.out.println(ldap.addUserGroup("harvey1","organizationalUnit"));
// System.out.println(ldap.addUserGroup("harvey2","organizationalRole"));
//添加用户
// System.out.println(ldap.addUser("czj333","123456"));
//重命名,组,用户
// System.out.println(ldap.renameEntry("cn=harvey,dc=ldap,dc=tydic,dc=org","cn=1232132,dc=ldap,dc=tydic,dc=org"));
// System.out.println(ldap.renameEntry("uid=czj333,dc=ldap,dc=tydic,dc=org","uid=liuzh,dc=ldap,dc=tydic,dc=org"));
//删除 组 用户
// System.out.println(ldap.delete("uid=liuzh,dc=ldap,dc=tydic,dc=org"));
// System.out.println(ldap.delete("cn=1232132,dc=ldap,dc=tydic,dc=org"));
//添加属性(注意邮箱属性是:mail,ldap页面上显示的是中文)
// 添加属性,如果一个属性不存在,则新添加一个属性,并赋值,如果一个属性已经存在,则再次赋值,就是一个属性可以有多个值
System.out.println(ldap.addAttribute("uid=czj333,dc=ldap,dc=tydic,dc=org","mail","123456"));
//修改属性
// System.out.println(ldap.modifyAttribute("uid=czj333,dc=ldap,dc=tydic,dc=org","title","123456"));
//删除属性
// System.out.println(ldap.deleteAttribute("uid=czj333,dc=ldap,dc=tydic,dc=org","title"));
//关闭连接
ldap.closeContext();
}
/**
* 连接ldap
*/
private void LDAP_connect() {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
env.put(Context.PROVIDER_URL, URL);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
String root = "cn=admin,dc=ldap,dc=tydic,dc=org"; //根据自己情况修改
env.put(Context.SECURITY_PRINCIPAL, root); // 管理员
env.put(Context.SECURITY_CREDENTIALS, "123456"); // 管理员密码 // 根据自己情况进行修改
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();
}
}
/**
* ldap连接关闭
*/
private void closeContext(){
if (ctx != null) {
try {
ctx.close();
}
catch (NamingException e) {
e.printStackTrace();
}
}
}
/**
* 查询用户或用户组
* @param cn
* @return
*/
private String getUserOrUserGroup(String cn) {
String userDN = "";
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
//查找用户,如果查找的是组,en=null
NamingEnumeration en = ctx.search(BASEDN, "cn=" + cn, constraints);
if (en == null || !en.hasMoreElements()) {
//查找组
en = ctx.search(BASEDN, "ou=" + cn, 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;
//操作属性
Attributes at = si.getAttributes();
NamingEnumeration ane = at.getAll();
while (ane.hasMore()) {
Attribute attr = (Attribute) ane.next();
String attrType = attr.getID();
NamingEnumeration values = attr.getAll();
Vector vals = new Vector();
while (values.hasMore()) {
Object oneVal = values.nextElement();
if (oneVal instanceof String) {
System.out.println(attrType + ": " + (String) oneVal);
} else {
System.out.println(attrType + ": " + new String((byte[]) oneVal));
}
}
}
} else {
System.out.println(obj);
}
}
} catch (Exception e) {
System.out.println("查找用户时产生异常。");
e.printStackTrace();
}
return userDN;
}
/**
* 添加用户
* @param usr
* @param pwd
* @return
*/
private boolean addUser(String usr, String pwd) {
try {
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", usr);
attrsbu.put("userPassword", pwd);
ctx.createSubcontext("uid="+usr+","+BASEDN, attrsbu);
return true;
} catch (NamingException ex) {
ex.printStackTrace();
}
return false;
}
/**
* 添加用户组
* @return
*/
private boolean addUserGroup(String groupName,String objectClass) {
try {
BasicAttributes attrsbu = new BasicAttributes();
BasicAttribute objclassSet = new BasicAttribute("objectclass");
//添加objectclass
objclassSet.add(objectClass);
objclassSet.add("top");
attrsbu.put(objclassSet);
if (objectClass.equals("posixGroup")){
attrsbu.put("cn", groupName);
attrsbu.put("gidNumber","507");
ctx.createSubcontext("cn="+groupName+","+BASEDN,attrsbu);
}
else if(objectClass.equals("organizationalUnit")){
attrsbu.put("ou", groupName);
ctx.createSubcontext("ou="+groupName+","+BASEDN,attrsbu);
}
else if (objectClass.equals("organizationalRole")){
attrsbu.put("cn", groupName);
ctx.createSubcontext("cn="+groupName+","+BASEDN,attrsbu);
}
return true;
} catch (NamingException ex) {
ex.printStackTrace();
}
return false;
}
/**
* 重命名节点
* @param oldDN
* @param newDN
* @return
*/
public boolean renameEntry(String oldDN, String newDN) {
try {
ctx.rename(oldDN, newDN);
return true;
} catch (NamingException ne) {
System.err.println("Error: " + ne.getMessage());
return false;
}
}
/**
* 删除
* @param dn
*/
public boolean delete(String dn) {
try {
ctx.destroySubcontext(dn);
return true;
} catch (Exception e) {
e.printStackTrace();
System.out.println("Exception in delete():" + e);
return false;
}
}
/**
* 添加属性
* @param dn 节点
* @param attributeName 属性名
* @param value 值
* @return
*/
public boolean addAttribute(String dn,String attributeName,String value) {
try {
System.out.println("add...\n");
ModificationItem[] mods = new ModificationItem[1];
/* 删除属性 */
// Attribute attr0 = new BasicAttribute("description",
// "陈轶");
// mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE,
// attr0);
/* 添加属性 */
Attribute attr0 = new BasicAttribute(attributeName,value);
mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr0);
/* 修改属性 */
ctx.modifyAttributes(dn, mods);
return true;
} catch (NamingException e) {
e.printStackTrace();
System.err.println("Error: " + e.getMessage());
return false;
}
}
/**
* 修改属性
* @param dn 节点
* @param attributeName 属性名
* @param value 值
* @return
*/
public boolean modifyAttribute(String dn,String attributeName,String value) {
try {
System.out.println("modify...\n");
ModificationItem[] mods = new ModificationItem[1];
/* 修改属性 */
Attribute attr0 = new BasicAttribute(attributeName, value);
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr0);
/* 修改属性 */
ctx.modifyAttributes(dn, mods);
return true;
} catch (NamingException e) {
e.printStackTrace();
System.err.println("Error: " + e.getMessage());
return false;
}
}
/**
* 删除属性
* @param dn 节点
* @param attributeName 属性名
* @param
* @return
*/
public boolean deleteAttribute(String dn,String attributeName) {
try {
System.out.println("delete...\n");
ModificationItem[] mods = new ModificationItem[1];
/* 删除属性 */
Attribute attr0 = new BasicAttribute(attributeName);
mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, attr0);
/* 修改属性 */
ctx.modifyAttributes(dn, mods);
return true;
} catch (NamingException e) {
e.printStackTrace();
System.err.println("Error: " + e.getMessage());
return false;
}
}
/**
* @param base :根节点(在这里是"dc=example,dc=com")
* @param scope :搜索范围,分为"base"(本节点),"one"(单层),""(遍历)
* @param filter :指定子节点(格式为"(objectclass=*)",*是指全部,你也可以指定某一特定类型的树节点)
*/
public void searchInformation(String base, String scope, String filter) {
SearchControls sc = new SearchControls();
if (scope.equals("base")) {
sc.setSearchScope(SearchControls.OBJECT_SCOPE);
} else if (scope.equals("one")) {
sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
} else {
sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
NamingEnumeration ne = null;
try {
ne = ctx.search(base, filter, sc);
// Use the NamingEnumeration object to cycle through
// the result set.
while (ne.hasMore()) {
System.out.println();
SearchResult sr = (SearchResult) ne.next();
String name = sr.getName();
if (base != null && !base.equals("")) {
System.out.println("entry: " + name + "," + base);
} else {
System.out.println("entry: " + name);
}
Attributes at = sr.getAttributes();
NamingEnumeration ane = at.getAll();
while (ane.hasMore()) {
Attribute attr = (Attribute) ane.next();
String attrType = attr.getID();
NamingEnumeration values = attr.getAll();
Vector vals = new Vector();
// Another NamingEnumeration object, this time
// to iterate through attribute values.
while (values.hasMore()) {
Object oneVal = values.nextElement();
if (oneVal instanceof String) {
System.out.println(attrType + ": " + (String) oneVal);
} else {
System.out.println(attrType + ": " + new String((byte[]) oneVal));
}
}
}
}
} catch (Exception nex) {
System.err.println("Error: " + nex.getMessage());
nex.printStackTrace();
}
}
public UserInfo authenricate(String UID, String password) {
String userDN = "";
String uidNumber="";
UserInfo userInfo=null;
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
//根据uid查找用户
NamingEnumeration en = ctx.search(BASEDN, "uid=" + UID, constraints);
while (en != null && en.hasMoreElements()) {
Object obj = en.nextElement();
if (obj instanceof SearchResult) {
SearchResult si = (SearchResult) obj;
userDN += si.getName();
userDN += "," + BASEDN;
//获取uidNumber属性
Attributes attributes = si.getAttributes();
Attribute attribute = attributes.get("uidNumber");
uidNumber=attribute.get(0).toString();
//封装属性
userInfo=new UserInfo();
userInfo.setUserId(Long.valueOf(uidNumber));
userInfo.setLoginName(UID);
userInfo.setPassword(password);
}
}
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
ctx.reconnect(connCtls);
System.out.println(userDN + " 验证通过");
} catch (AuthenticationException e) {
System.out.println(userDN + " 验证失败");
System.out.println(e.toString());
} catch (NamingException e) {
System.out.println(userDN + " 验证失败");
}
return userInfo;
}
}
参考:https://jianshi-dlw.iteye.com/blog/1557846
https://blog.csdn.net/binyao02123202/article/details/18697953