LDAP (Lightweight Directory Access Protocol) : 轻量目录访问协议
LDAP是一个跨平台的、标准的协议
LDAP支持TCP/IP
LDAP也是有client端和server端。server端是用来存放资源,client端用来操作增删改查等操作
LDAP是一个到目录服务的目录访问协议
目录服务:简单来讲是为了浏览和搜索数据而设计的特殊数据库
LDAP 类似于用一个树状结构将数据联系起来(和查询DNS服务挺类似的),大致如图所示:
PS. LDAP 中的数据不常用来修改
缩写 | 全称 | 含义 |
---|---|---|
dc | Domain Component | 域名的部分,其格式是将完整的域名分成几部分,如dc=domain,dc=com |
uid | User Id | 用户ID, 如"test" |
ou | Organization Unit | 组织单位,类似于Linux文件系统中的子目录,是一个容器对象,可以包含其他各种对象 |
cn | Common Name | 公共名称 |
sn | Surname | 姓 |
dn | Distinguished Name | 唯一辨别名,类似于绝对路径,如"uid=test,ou=sec,dc=domain,dc=com",在一个目录树中dn总是唯一的 |
rdn | Relative dn | 相对辨别名,类似相对路径 |
c | Country | 国家 |
o | Organization | 组织名 |
Directory | 目录,用于存放信息的单元 |
Entry | 条目,一个entry就是一条记录,是LDAP中一个基本的存储单元 |
DN:Distinguished Name | 条目中用于唯一区别改条目的信息 |
LDIF:LDAP Interchange Format | 用于规范LDAP的配置和目录内容等详细信息的保存 |
Objectclass | LDAP对象类,是LDAP内置的数据模型。每种objectClass有自己的数据结构 |
PS.
可以用JNDI的方式
如之前在JNDI中提到的
ldap://localhost:389/...
jdbc:ldap://localhost:389/...
java代码也与之前在JNDI中举例的类似
一个简易的连接LDAP服务器完整Java代码为
ximport javax.naming.Context;
import javax.naming.Name;
import javax.naming.InitialContext;
import java.util.Hashtable;
public class ldap{
public static void main(String[] args) throws Exception{
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
// LDAP服务器的位置,以及认证信息(如果有的话
env.put(Context.PROVIDER_URL, "ldap://localhost:389/");
env.put(Context.SECURITY_PRINCIPAL, "user");
env.put(Context.SECURITY_CREDENTIALS, "password");
// 根辨别名是“o=JNDITutorial”,此处无需认证
// env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=Test");
Context ctx = new InitialContext(env); // 创建初始化上下文
// ...
// 一些具体的查询之类的操作就不写了
}
}
sudo apt install slapd ldap-utils
slapd -h "ldap://:1234"
指定为1234端口启动
pom.xml
xxxxxxxxxx
<dependencies>
<dependency>
<groupId>com.unboundid</groupId>
<artifactId>unboundid-ldapsdk</artifactId>
<version>4.0.8</version>
</dependency>
</dependencies>
xxxxxxxxxx
public class LDAPSeriServer {
private static final String LDAP_BASE = "dc=example,dc=com";
public static void main(String[] args) throws IOException {
int port = 37777;
try {
InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);
config.setListenerConfigs(new InMemoryListenerConfig(
"listen", InetAddress.getByName("0.0.0.0"), port,
ServerSocketFactory.getDefault(), SocketFactory.getDefault(),
(SSLSocketFactory) SSLSocketFactory.getDefault()
));
config.setSchema(null);
config.setEnforceAttributeSyntaxCompliance(false);
config.setEnforceSingleStructuralObjectClass(false);
InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
ds.add("dn: " + "dc=example,dc=com", "objectClass: top", "objectclass: domain");
System.out.println("Listening on 0.0.0.0:" + port);
ds.startListening();
} catch (Exception e) {
e.printStackTrace();
}
}
}
用于规范LDAP的配置和目录内容等详细信息的保存
一个LDIF文件的格式大致为
xxxxxxxxxx
# 注释,用于对条目进行解释
dn:条目名称
objectClass(对象类): 属性值
objectClass(对象类): 属性值
...
xxx: xxx
...
如:
xxxxxxxxxx
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.
# CRC32 f0235778
dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/slapd/slapd.args
olcLogLevel: none
olcPidFile: /var/run/slapd/slapd.pid
olcToolThreads: 1
structuralObjectClass: olcGlobal
entryUUID: b9f37eae-50bd-103a-939b-09e7b1ef64f4
creatorsName: cn=config
createTimestamp: 20200702141032Z
entryCSN: 20200702144032.300123Z#000000#000#000000
modifiersName: cn=config
modifyTimestamp: 20200702141032Z
可使用Context.lookup("ldap://<ip>:<port>/xxx")
如Context.lookup("ldap://127.0.0.1:37777/dc=example,dc=com");
LDAP和LDAPS 的关系类似于 HTTP与HTTPS
LDAPS: LDAP over SSL(LDAPS)