LDAP介绍
介绍
LDAP是域的一种管理系统。
LDAP的存储结构为树状结构,由父节点、子节点、叶子节点组成。
概念
Entry
条目,LDAP系统中最基本的颗粒,类似于数据库的记录。通常对LDAP的增删查改是以条目为基本对象。
dn
相当于条目的id,通常由包含ou、cn、dc等组成,例如:cn=test_test_1_6_210,ou=test3,ou=test2,ou=test_group,ou=Users
。LDAP能通过dn清晰表示出该条目在LDAP系统中的位置。
Attribute
条目的属性
用户属性
userAccountControl
属性标志 | 十六进制值 | 十进制值 | 说明 |
SCRIPT | 0x0001 | 1 | 将运行登录脚本 |
ACCOUNTDISABLE | 0x0002 | 2 | 禁用用户帐户 |
HOMEDIR_REQUIRED | 0x0008 | 8 | 需要主文件夹 |
LOCKOUT | 0x0010 | 16 | 不需要密码 |
PASSWD_NOTREQD | 0x0020 | 32 | 用户不能更改密码。可以读取此标志,但不能直接设置它 |
ENCRYPTED_TEXT_PWD_ALLOWED | 0x0080 | 128 | 用户可以发送加密的密码 |
TEMP_DUPLICATE_ACCOUNT | 0x0100 | 256 | 此帐户属于其主帐户位于另一个域中的用户。此帐户为用户提供访问该域的权限,但不提供访问信任该域的任何域的权限。有时将这种帐户称为“本地用户帐户 |
NORMAL_ACCOUNT | 0x0200 | 512 | 典型用户的默认帐户类型 |
INTERDOMAIN_TRUST_ACCOUNT | 0x0800 | 2048 | 对于信任其他域的系统域,此属性允许信任该系统域的帐户 |
WORKSTATION_TRUST_ACCOUNT | 0x1000 | 4096 | 运行 Microsoft Windows NT 4.0 Workstation、Microsoft Windows NT 4.0 Server、Microsoft Windows 2000 Professional 或 Windows 2000 Server 并且属于该域的计算机的计算机帐户 |
SERVER_TRUST_ACCOUNT | 0x2000 | 8192 | 属于该域的域控制器的计算机帐户 |
DONT_EXPIRE_PASSWORD | 0x10000 | 65536 | 在该帐户上永远不会过期的密码 |
MNS_LOGON_ACCOUNT | 0x20000 | 131072 | MNS 登录帐户 |
SMARTCARD_REQUIRED | 0x40000 | 262144 | 设置此标志后,将强制用户使用智能卡登录 |
TRUSTED_FOR_DELEGATION | 0x80000 | 524288 | 设置此标志后,将信任运行服务的服务帐户(用户或计算机帐户)进行 Kerberos 委派。任何此类服务都可模拟请求该服务的客户端。若要允许服务进行 Kerberos 委派,必须在服务帐户的userAccountControl 属性上设置此标志 |
NOT_DELEGATED | 0x100000 | 1048576 | 设置此标志后,即使将服务帐户设置为信任其进行 Kerberos 委派,也不会将用户的安全上下文委派给该服务 |
USE_DES_KEY_ONLY | 0x200000 | 2097152 | (Windows 2000/Windows Server 2003) 将此用户限制为仅使用数据加密标准 (DES) 加密类型的密钥。 |
DONT_REQ_PREAUTH | 0x400000 | 4194304 | (Windows 2000/Windows Server 2003) 此帐户在登录时不需要进行 Kerberos 预先验证 |
PASSWORD_EXPIRED | 0x800000 | 8388608 | (Windows 2000/Windows Server 2003) 用户的密码已过期 |
TRUSTED_TO_AUTH_FOR_DELEGATION | 0x1000000 | 16777216 | (Windows 2000/Windows Server 2003) 允许该帐户进行委派。这是一个与安全相关的设置。应严格控制启用此选项的帐户。此设置允许该帐户运行的服务冒充客户端的身份,并作为该用户接受网络上其他远程服务器的身份验证 |
ObjectClass
条目的属性的集合
Schema
ObjectClass的集合。确保从外部导入数据到LDAP时的数据结构与现有数据结构一致性。
backend
读写数据的操作的单元模块
database
存储数据
缩写
缩写 | 全称 | 内容 |
DC | Domain Component | 域名的部分,其格式是将完整的域名分成几部分,如域名为example.com变成dc=example,dc=com |
UID | User Id | 用户ID songtao.xu(一条记录的ID) |
OU | Organization Unit | 组织单位,组织单位可以包含其他各种对象(包括其他组织单元),如“oa组”(一条记录的所属组织) |
CN | Common Name | 公共名称,如“Thomas Johansson”(一条记录的名称) |
SN | Surname | 姓,如“许” |
DN | Distinguished Name | “uid=songtao.xu,ou=oa组,dc=example,dc=com”,一条记录的位置(唯一) |
RDN | Relative dn | 相对辨别名,类似于文件系统中的相对路径,它是与目录树结构无关的部分,如“uid=tom”或“cn= Thomas Johansson” |
springboot整合
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>
ladp版本跟随springboot版本即可
配置项
spring:
ldap:
urls: ldap://123:389
base: dc=123-123,dc=cn
username: cn=123,dc=123,dc=cn
password: asdf
jackson:
serialization:
# 不关闭jackson序列化,输出Name类型的dn会报错
FAIL_ON_EMPTY_BEANS: false
实体类
base只填写至ou部分即可
objectClass从这里找,此界面为php-ldap-admin
成员
package com.me.ldap.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;
import org.springframework.ldap.support.LdapNameBuilder;
import javax.naming.Name;
import javax.naming.ldap.LdapName;
import java.io.Serializable;
import java.util.List;
/**
* @author Wuzhiming
*/
@Entry(objectClasses = {"inetOrgPerson"}, base = "ou=Users")
public class Person implements Serializable {
private static final long serialVersionUID = 2537331577057988415L;
@Id
private Name dn;
/**
* 用户唯一标识
*/
@Attribute(name = "cn")
private String cn;
@Attribute(name = "sn")
private String sn;
@Attribute(name = "userPassword")
private String userPassword;
@Attribute(name = "ou")
private String groupName;
@Attribute(name = "userAccountControl")
private String userAccountControl;
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public String getUserAccountControl() {
return userAccountControl;
}
public void setUserAccountControl(String userAccountControl) {
this.userAccountControl = userAccountControl;
}
public Person(String cn) {
LdapName dn = LdapNameBuilder.newInstance()
.add("o", "Users")
.add("cn", cn)
.add("dc", "yuang-group")
.build();
this.dn = dn;
}
public Person(String cn, String groupName) {
LdapName dn = LdapNameBuilder.newInstance()
.add("o", groupName)
.add("cn", cn)
.add("dn", "Users")
.add("dc", "yuang-group")
.build();
this.dn = dn;
}
public Person() {
}
/**
* getter
*/
public Name getDn() {
return dn;
}
public String getCn() {
return cn;
}
public String getSn() {
return sn;
}
public String getUserPassword() {
return userPassword;
}
/** setter */
public void setDn(Name dn) {
this.dn = dn;
}
public void setCn(String cn) {
this.cn = cn;
}
public void setGroup(String groupName) {
if (this.dn == null) {
LdapName dn = LdapNameBuilder.newInstance()
.add("ou","Users")
.add("ou", groupName)
.add("cn",cn)
.build();
this.dn = dn;
}
}
public void setGroup(List<String> groupNameList) {
if (this.dn == null) {
LdapNameBuilder builder = LdapNameBuilder.newInstance()
.add("ou", "Users");
for (String groupName : groupNameList) {
builder=builder.add("ou",groupName);
}
LdapName dn = builder.add("cn", cn).build();
this.dn = dn;
}
}
public void setSn(String sn) {
this.sn = sn;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
@Override
public String toString() {
return "Person{" +
"dn=" + dn +
", cn='" + cn + '\'' +
", sn='" + sn + '\'' +
", userPassword='" + userPassword + '\'' +
", groupName='" + groupName + '\'' +
'}';
}
}
成员组
package com.me.ldap.domain;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;
import org.springframework.ldap.support.LdapNameBuilder;
import javax.naming.Name;
import java.util.List;
@Entry(objectClasses = {"organizationalUnit","top"},base = "ou=Users")
public class Group {
@Id
private Name dn;
@Attribute(name = "ou")
private String name;
public Name getDn() {
return dn;
}
public void setGroupName(List<String> groupNameList) {
if(this.dn==null){
LdapNameBuilder builder = LdapNameBuilder.newInstance();
builder.add("ou","Users");
for (String groupName : groupNameList) {
builder=builder.add("ou",groupName);
}
dn=builder.build();
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Group{" +
"dn=" + dn +
", name='" + name + '\'' +
'}';
}
}
前端传参接收类
用户
package com.me.ldap.domain.param;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;
import org.springframework.ldap.support.LdapNameBuilder;
import javax.naming.Name;
import java.io.Serializable;
import java.util.List;
/**
* @author Wuzhiming
*/
@Data
public class AddPersonParam implements Serializable {
private static final long serialVersionUID = -3761043026736955966L;
private List<String> groupName;
private String cn;
private String sn;
private String userPassword;
}
用户组
package com.me.ldap.domain.param;
import lombok.Data;
import java.util.List;
/**
* @author Wuzhiming
*/
@Data
public class AddGroupParam {
private List<String> groupNameList;
}
增删查改
查询
查询单个用户
public Person getPersonByCn(String cn) {
Person cn1 = ldapTemplate.findOne(query().where("cn").is(cn), Person.class);
return cn1;
}
查询所有用户(只包含在base下的)
public List<Person> getAll() {
return ldapTemplate.findAll(Person.class);
}
新增
/**
* 创建用户
*
* @param personParam
*/
public void create(AddPersonParam personParam) {
Person person = new Person();
BeanCopier beanCopier = BeanCopier.create(AddPersonParam.class, Person.class, false);
beanCopier.copy(personParam, person, null);
person.setGroup(personParam.getGroupName());
System.out.println(person);
ldapTemplate.create(person);
}
{
"groupName": ["test_group","test2","test3"],
"cn": "test_test_1_6_20",
"sn": "114851418",
"userPassword": "123456abcABC."
}
注意事项
- 只能在${base}组和以下级别的节点上创建用户。
- 添加用户前必须先创建用户组,create()不能级联创建用户组。
- 非{base}级别以下的成员组中加入用户,则需要写上此成员组及所有成员组名(${base}除外)
- cn必须保证全局唯一
删除
删除本节点
public void deletePerson(String personCn) {
Person person = this.getPersonByCn(personCn);
System.out.println(person);
ldapTemplate.delete(person);
}
注意事项
- 删除本节点时,本节点不能有任何子节点,否则会报错
级联删除
Group group = new Group();
BeanCopier beanCopier = BeanCopier.create(AddGroupParam.class, Group.class, false);
beanCopier.copy(param, group, null);
group.setGroupName(param.getGroupNameList());
System.out.println(group);
ldapTemplate.unbind(group.getDn(),true);