前言
本文介绍LDAP目录服务器的简单概念以及如何使用Java操作LDAP作目录服务器
正文
什么是目录服务器?
目录是一个专门为搜索和浏览而设计的数据库,它也支持简单的插入、删除、修改功能。你可以把它理解为我们传统使用的关系型数据库,但是他与我们的关系型数据库有着本质的区别,目录的存储结构类似于linux文件系统,他是一颗树(类似下图),由于它是为浏览和搜索而设计的,它的查询速度很快,相反插入速度较慢,它也不支持事务和回滚以及复杂的插入、更新功能。目录服务器可像关系型数据库一样对外提供数据服务,它可以是单机或集群式的。在集群式的架构中每个机器都拥有一致的数据备份。
树中的每个节点称之为条目(Entry),目录服务是以条目为基础的,在上图的树型结构中,每个条目都有一个唯一的绝对名字Directory Name(DN)和相对名字rDN。每个条目具有一组属性,每个属性有一个key,每个key对应一个或多个value。具体每个条目有哪些属性由ObjectClass约束,也就是说每个条目通过赋予ObjectClass来规定其必须拥有的属性。
例如上图的babs条目中:
DN:uid=babs,ou=people,dc=example,dc=com
相对于ou=people,dc=example,dc=com 节点的rDN:uid=babs
ObjectClass:Person
什么是LDAP?
LDAP全称为Lightweight Directory Access Protocol(轻量级目录访问协议),客户端与目录服务器遵循LDAP协议来发生交互,比如说新增一个节点,查询某个节点的属性等等。
常见的LDAP目录服务器
与关系型数据库一样,LDAP目录服务器是一个概念,包含许多具体实现的产品,比如关系型数据库常见的有MySQL,Oracle等等。LDAP目录服务器也有常见的具体实现,比如:OpenLDAP,Active Directory(Microsoft)。本文以OpenLDAP为例介绍Java如何操作LDAP服务器。
什么时候使用LDAP目录服务器?
看到目前为止,你可能会觉得目录服务器貌似和关系型数据库服务器没有什么区别,到底什么时候该使用目录服务器呢?
使用目录服务器最常见的情况就是多系统间的集中用户管理,比如公司会使用OA,Confluence,gitlab,jira等等办公系统。如果每个系统都需要我们记住一个账号密码,那无疑是很费力的。通过使用LDAP目录服务器将多个应用的用户集中管理起来,每个应用都通过通用的LDAP协议与目录服务器通信,达到用户信息集中管理的目的。事实上很多的开源项目都支持LDAP用户认证(例如SuperSet,Hue等等)
代码示例
package richstonedt.com;
import com.novell.ldap.*;
import com.novell.ldap.util.Base64;
import lombok.extern.slf4j.Slf4j;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/** * 参考地址:http://www.micmiu.com/opensource/java-ldap-demo/ */
@Slf4j
public class App {
private static String ldapHost = "192.168.x.x";
private static int ldapPort = 389;
private static String ldapBindDN = "cn=Manager,dc=my-domain,dc=com";
private static String ldapPassword = "123456";
private static int ldapVersion = LDAPConnection.LDAP_V3;
/** * 获取连接 * * @return A LDAP Connection * @throws LDAPException * @throws UnsupportedEncodingException */
@SuppressWarnings("deprecation")
private static LDAPConnection connection() throws UnsupportedEncodingException, LDAPException {
try {
LDAPConnection lc = new LDAPConnection();
//获取连接
lc.connect(ldapHost, ldapPort);
//认证
lc.bind(ldapVersion, ldapBindDN, ldapPassword.getBytes("UTF8"));
log.info("连接LDAP服务器成功!");
return lc;
} catch (Exception e) {
log.debug("LDAP服务器连接失败!");
throw e;
}
}
/** * 搜索某目录节点下所有节点及其属性 * @param DN 目录节点名 * @throws LDAPException * @throws UnsupportedEncodingException */
public static void searchEntry(String DN) throws LDAPException, UnsupportedEncodingException {
LDAPConnection conn = connection();
try {
LDAPSearchResults searchResults = conn.search(DN,
LDAPConnection.SCOPE_SUB, "objectClass=*", null, false);
while (searchResults.hasMore()) {
LDAPEntry nextEntry;
try {
nextEntry = searchResults.next();
} catch (LDAPException e) {
log.debug("Error: " + e);
if (e.getResultCode() == LDAPException.LDAP_TIMEOUT
|| e.getResultCode() == LDAPException.CONNECT_ERROR) {
break;
} else {
continue;
}
}
log.info("DN :" + nextEntry.getDN());
log.info("|---- Attributes list: ");
LDAPAttributeSet attributeSet = nextEntry.getAttributeSet();
Iterator<LDAPAttribute> allAttributes = attributeSet.iterator();
while (allAttributes.hasNext()) {
LDAPAttribute attribute = allAttributes.next();
String attributeName = attribute.getName();
Enumeration<String> allValues = attribute.getStringValues();
if (null == allValues) {
continue;
}
while (allValues.hasMoreElements()) {
String value = allValues.nextElement();
if (!Base64.isLDIFSafe(value)) {
// base64 encode and then print out
value = Base64.encode(value.getBytes());
}
log.info("|---- ---- " + attributeName
+ " = " + value);
}
}
}
} finally {
if (conn.isConnected()) {
conn.disconnect();
}
}
}
/** * 新增一个目录节点 * @param baseDN * @param rDN * @param attribute * @throws UnsupportedEncodingException * @throws LDAPException */
public static void addEntry(String baseDN, String rDN, Map<String, String> attribute) throws UnsupportedEncodingException, LDAPException {
LDAPConnection conn = connection();
try {
LDAPAttributeSet attributeSet = new LDAPAttributeSet();
for (Map.Entry<String, String> entry : attribute.entrySet()) {
attributeSet.add(new LDAPAttribute(entry.getKey(), entry.getValue()));
}
String DN = rDN + "," + baseDN;
conn.add(new LDAPEntry(DN, attributeSet));
} finally {
if (conn.isConnected())
conn.disconnect();
}
}
/** * 删除一个目录节点 * @param DN 目录节点名 * @throws UnsupportedEncodingException * @throws LDAPException */
public static void deleteEntry(String DN) throws UnsupportedEncodingException, LDAPException {
LDAPConnection conn = connection();
try {
conn.delete(DN);
} finally {
if (conn.isConnected()) {
conn.disconnect();
}
}
}
public static void main(String[] args) throws UnsupportedEncodingException, LDAPException {
//新增节点
Map<String, String> map = new HashMap<>();
map.put("objectclass", "inetOrgPerson");
map.put("cn", "liuruojing");
map.put("sn", "liuruojing");
addEntry("ou=userAccount,dc=my-domain,dc=com", "uid=liuruojing", map);
//查询节点
searchEntry("uid=liuruojing,ou=userAccount,dc=my-domain,dc=com");
//删除节点
deleteEntry("uid=liuruojing,ou=userAccount,dc=my-domain,dc=com");
}
}
注意:需要引入JLDAP的Maven依赖
<dependency>
<groupId>com.novell.ldap</groupId>
<artifactId>jldap</artifactId>
<version>4.3</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
今天的文章LDAP目录服务器介绍分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/14957.html