文章目录
1 ldap 是什么
https://www.cnblogs.com/yjd_hycf_space/p/7994597.html
ldap: Lightweight Directory Access Protocol,也就是轻量目录访问协议。协议规范对应的 RFC 文档可以在 https://www.rfc-editor.org/ 或者 http://www.ldapman.org/ 中查找。
可以简单的将其理解为一个树形结构的数据库,有以下特征:
- 存储单元是基于属性的记录;
- 数据类型主要是字符型;
- 主要面向以快速查询为主的应用服务(查询与修改比例大于 10)
- 提供复杂的不同层次的访问控制
2 ldap 基本模型
2.1 数据模型
数据模型 = (名称,地址,类型,值)
在 ldap 中数据是以树状方式来组织和存储的,树状结构中的每一个节点都对应一个 ldap 条目(entry),entry 的数据模型对应为:
(名称,地址,类型,值)= (rdn,dn,[ objectclass_1, objectclass_2, …], { key = value}).
ldap 中的 entry 有的类型是通过 objectclass 来定义的,每个 ObjectClass 由多个属性类型(attribute type)组成;对象类(objectclass)和属性类型(attribute type)都有继承的概念。
在 ldap 中把对象类,属性类型,语法和匹配规则统称为 schema;可以简单的这么理解:
- objectclass 对应于关系数据库中的 table
- attribute type 对应于关系数据库中的 column type
ldap 已经预定义了很多 schema,也可以根据需要自定义 schema。
ldap 为了加快查询速度,在 schema 中有匹配规则的概念,针对不同的数据类型,可以提供不同的匹配方法,如针对字符串类型的相等、模糊、大于、小于,都可以提供自己的匹配规则。
2.2 命名模型
ldap 中的命名模型,DN(distinguish name),RDN(Relative Distinguished Name)。
DN 是 ldap entry 在整个树中的唯一名称标识,RDN 是节点名称,可以简单的用文件系统中文件路径和文件名的概念来理解,DN 就是文件在系统中的绝对路径,比如 /opt/china/baidu/develop/xiaowang,而 RDN 就是文件名称 xiaowang。
2.3 功能模型
在 ldap 中有多种操作:
- 查询:搜索,比较
- 更新:add,delete,modify
- 认证:bind,unbind
- others
2.4 安全模型
ldap 中的安全模型主要通过身份认证、安全通道和访问控制来实现。
3 openLDAP服务器
openLDAP 官网: http://www.openldap.org/
用户手册:http://www.openldap.org/doc/admin24/OpenLDAP-Admin-Guide.pdf
openLDAP 是 ldap 的开源实现.
首先按照默认配置安装 openLDAP。
配置: slapd.conf
suffix “dc=example,dc=com”
rootdn “cn=Manager,dc=example,dc=com”
spring ldap 中的 ContextSource 则对应如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ldap="http://www.springframework.org/schema/ldap"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/ldap http://www.springframework.org/schema/ldap/spring-ldap.xsd">
<ldap:context-source
url="ldap://localhost:389"
base="dc=example,dc=com"
username="cn=Manager"
password="secret" />
<ldap:ldap-template id="ldapTemplate" />
<bean id="personRepo" class="com.example.repo.PersonRepoImpl">
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>
</beans>
如果通过 LDAP Admin 来访问 openLdap,建立 connection 时,需要配置如下:
4 Spring LDAP
官网: http://projects.spring.io/spring-ldap/
Spring LDAP 基于 ldapTemplate 来简化 ldap 操作,用户在使用 ldapTemplate 时,就无需考虑资源的释放等问题了,类似于 JdbcTemplate。
- 提供 LdapTemplate 来消除一些重复的框架代码;
- 提供了一套规范的、结构化的异常体系;
- 提供了一些动态构建 LDAP filters 和 Distinguished Names 的工具类;
- 客户端 LDAP 事务管理;
- …
4.1 构建 LDAP queries,并使用 AttributeMapper 进行查询和搜索
ldapTemplate.search(
query().where("objectclass").is("person"),
new AttributesMapper<String>() {
public String mapFromAttributes(Attributes attrs)
throws NamingException {
return (String) attrs.get("cn").get();
}
});
可以通过 query() 构建复杂的过滤规则,类似于 SQL,比如:
LdapQuery query = query().base("dc=261consulting,dc=com")
.attributes("cn", "sn")
.where("objectclass").is("person")
.and("sn").is("tom");
AttributesMapper 是一个回调接口,如果想要获取 entity 的 dn 信息的话,可以使用 ContextMapper。
4.2 动态构建 DN
LdapName 是 J2SE 中定义的 DN 接口,但是比较弱,Spring ldap 又提供了其他几个工具类来辅助对 DN 的操作,比如 LDAPNameBuilder, LdapUtils。
final String BASE_DN = "dc=example,dc=com";
Name name = LdapNameBuilder.newInstance(BASE_DN)
.add("c", p.getCountry())
.add("ou", p.getCompany())
.add("cn", p.getFullname())
.build();
需要注意 ldap 中节点的顺序,比如 DN = ‘cn=xiaoming, ou=baidu, c=china, dc=example, dc=com’。
name.get(0) == "c=china";
name.get(1) == "ou=baidu";
name.get(2) == "cn=xiaoming";
4.3 添加,删除与更新
在 ldap 中通过 Binding 来实现数据节点的添加,通过 unbinding 来实现数据节点的删除。
ldapTemplate.bind(dn, null, attributes);
ldapTemplate.unbind(dn);
其中 attributes 就是 entry 的属性数据,可以通过如下方式构建:1
Attributes attrs = new BasicAttributes();
BasicAttribute ocattr = new BasicAttribute("objectclass");
ocattr.add("top");
ocattr.add("person");
attrs.put(ocattr);
attrs.put("cn", "Some Person");
attrs.put("sn", "Person");
return attrs;
数据更新有两种方式:rebind,和 modifyAttributes,其中 rebind 就是先 unbind 再 bind,稍显暴力。另外还可以通过 DirContextOperations 来简化 modifyAttributes 的使用。
4.4 属性映射,ODM
Object-Directory Mapping, 与 Hibernate 的功能类似,就是将 ldap 中的 entry 映射为 java 中的对象。
。。。。
4.5 用户认证: User Authentication
可以通过 ldapTempalate 中的 authenticate 接口来实现用户认证:
ldapTemplate.authenticate(query().where("uid").is("john.doe"), "secret");
认证失败时会抛出异常!!
5 总结
把 ldap 当成数据库来看就对了,想更详细的了解 ldap 规范和 spring ldap,就去查阅官网吧!