LDAP(Light Directory Access Portocol),它是基于X.500标准的轻量级目录访问协议。
目录是一个为查询、浏览和搜索而优化的数据库,它成树状结构组织数据,类似文件目录一样。
目录数据库和关系数据库不同,它有优异的读性能,但写性能差,并且没有事务处理、回滚等复杂功能,不适于存储修改频繁的数据。所以目录天生是用来查询的,就好象它的名字一样。
LDAP目录服务是由目录数据库和一套访问协议组成的系统。
每一个系统、协议都会有属于自己的模型,LDAP也不例外,在了解LDAP的基本模型之前我们需要先了解几个LDAP的目录树概念:
(一)目录树概念
1. 目录树:在一个目录服务系统中,整个目录信息集可以表示为一个目录信息树,树中的每个节点是一个条目。
2. 条目:每个条目就是一条记录,每个条目有自己的唯一可区别的名称(DN)。
3. 对象类:与某个实体类型对应的一组属性,对象类是可以继承的,这样父类的必须属性也会被继承下来。
4. 属性:描述条目的某个方面的信息,一个属性由一个属性类型和一个或多个属性值组成,属性有必须属性和非必须属性。
(二)DC、UID、OU、CN、SN、DN、RDN
关键字 |
英文全称 |
含义 |
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” |
LDAP中,一个条目必须包含一个objectClass属性,且需要赋予至少一个值。每一个值将用作一条LDAP条目进行数据存储的模板;模板中包含了一个条目必须被赋值的属性和可选的属性。
objectClass有着严格的等级之分,最顶层是top和alias。例如,organizationalPerson这个objectClass就隶属于person,而person又隶属于top。
objectClass可分为以下3类:
在OpenLDAP的schema中定义了很多objectClass,下面列出部分常用的objectClass的名称。
● account
● alias
● dcobject
● domain
● ipHost
● organization
● organizationalRole
● organizationalUnit
● person
● organizationalPerson
● inetOrgPerson
● residentialPerson
● posixAccount
● posixGroup
属性(Attribute)类似于程序设计中的变量,可以被赋值。在OpenLDAP中声明了许多常用的Attribute(用户也可自己定义Attribute)。常见的Attribute含义如下:
● c:国家。
● cn:common name,指一个对象的名字。如果指人,需要使用其全名。
● dc:domain Component,常用来指一个域名的一部分。
● givenName:指一个人的名字,不能用来指姓。
● l:指一个地名,如一个城市或者其他地理区域的名字。
● mail:电子信箱地址。
● o:organizationName,指一个组织的名字。
● ou:organizationalUnitName,指一个组织单元的名字。
● sn:surname,指一个人的姓。
● telephoneNumber:电话号码,应该带有所在的国家的代码。
● uid:userid,通常指某个用户的登录名,与Linux系统中用户的uid不同。
对于不同的objectClass,通常具有一些必设属性值和一些可选属性值。例如,可使用person这个objectClass来表示系统中一个用户的条目,对于系统中用户通常需要有这样一些信息:姓名、电话、密码、描述等。如下图所示,对于person,通过cn和sn设置用户的名和姓,这是必须设置的,而其他属性则是可选的。
下面列出部分常用objectClass要求必设的属性。
● account:userid。
● organization:o。
● person:cn和sn。
● organizationalPerson:与person相同。
● organizationalRole:cn。
● organizationUnit:ou。
● posixGroup:cn、gidNumber。
● posixAccount:cn、gidNumber、homeDirectory、uid、uidNumber。
userAccountControl记录了用户的AD账号的很多属性信息,该属性标志是累积性的。若要禁用用户的帐户,请将 UserAccountControl 属性设置为 0x0202 (0x002 + 0x0200)。在十进制中,它是 514 (2 + 512)。
Microsoft官方网站有详尽的解释。
但有时汇出的资料并不完全都是下面的数值,经常会出现514、66048等不在下列列表中的数值。
哈哈。。。看到“该属性标志是累积性的”的意思大家应该明白了。514可以看成是512+2 ,66048可以看成是65536+512
对应最后的解释,所以:
514=512+2=账号存在且关闭
66045=65536+512=密码永不过期+账号正常
属性标志 |
十六进制值 |
十进制值 |
SCRIPT |
0x0001 |
1 |
ACCOUNTDISABLE |
0x0002 |
2 |
HOMEDIR_REQUIRED |
0x0008 |
8 |
LOCKOUT |
0x0010 |
16 |
PASSWD_NOTREQD |
0x0020 |
32 |
PASSWD_CANT_CHANGE |
0x0040 |
64 |
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 |
SERVER_TRUST_ACCOUNT |
0x2000 |
8192 |
DONT_EXPIRE_PASSWORD |
0x10000 |
65536 |
MNS_LOGON_ACCOUNT |
0x20000 |
131072 |
SMARTCARD_REQUIRED |
0x40000 |
262144 |
TRUSTED_FOR_DELEGATION |
0x80000 |
524288 |
NOT_DELEGATED |
0x100000 |
1048576 |
USE_DES_KEY_ONLY |
0x200000 |
2097152 |
DONT_REQ_PREAUTH |
0x400000 |
4194304 |
PASSWORD_EXPIRED |
0x800000 |
8388608 |
TRUSTED_TO_AUTH_FOR_DELEGATION |
0x1000000 |
16777216 |
属性标志说明:
spring-ldap github源码:GitHub - spring-projects/spring-ldap: Spring LDAP
spring-ldap 官方文档:Spring LDAP Reference
org.springframework.ldap
spring-ldap-core
2.3.2.RELEASE
新增一个properties,存储连接ldap基础信息:
ldap.host=192.168.1.153
ldap.port=389
ldap.userDn=cn=administrator,cn=Users,DC=inter-**,DC=net
ldap.passwd=******
ldap.baseDn=DC=inter-**,DC=net
import com.alibaba.fastjson.JSON;
import com.lxhr.common.util.string.GetterUtil;
import com.lxhr.ldap.entity.LdapUser;
import com.lxhr.ldap.mapper.LdapGroupAttributeMapper;
import com.lxhr.ldap.mapper.LdapPersonAttributeMapper;
import com.lxhr.ldap.pojo.Group;
import com.lxhr.ldap.pojo.Person;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.ldap.filter.WhitespaceWildcardsFilter;
import org.springframework.ldap.query.LdapQuery;
import org.springframework.ldap.query.LdapQueryBuilder;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.naming.NamingEnumeration;
import javax.naming.directory.*;
import javax.naming.ldap.LdapName;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* ldap测试类 https://docs.spring.io/spring-ldap/docs/2.3.2.RELEASE/reference/
* 514=512+2=账号存在且关闭
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:conf/spring.xml","classpath:conf/spring-mybatis.xml","classpath:conf/spring-mongodb.xml"})
public class LdapTest {
public static final String BASE_DN = "DC=inter-**,DC=net";
int UF_ACCOUNTDISABLE = 0x0002;
int UF_PASSWD_NOTREQD = 0x0020;
int UF_PASSWD_CANT_CHANGE = 0x0040;
int UF_NORMAL_ACCOUNT = 0x0200;
int UF_DONT_EXPIRE_PASSWD = 0x10000;
int UF_PASSWORD_EXPIRED = 0x800000;
@Autowired
private LdapTemplate ldapTemplate;
/**
* 新增分组
*/
@Test
public void saveGroup() {
Map map = new HashMap<>();
map.put("ou","测试test部门");
String pou = "HR集团,青岛";
this.insertOu(map, pou);
}
private void insertOu(Map map, String pou) {
Attributes ouAttributes=new BasicAttributes();
BasicAttribute ouBasicAttribute=new BasicAttribute("objectclass");
ouBasicAttribute.add("top");
ouBasicAttribute.add("organizationalUnit");
ouAttributes.put(ouBasicAttribute);
for(String str:map.keySet()){
if(StringUtils.isNotBlank(map.get(str))) {
ouAttributes.put(str,map.get(str));
}
}
// LdapName ldapName = LdapNameBuilder.newInstance().add("ou","HR集团").add("ou","事业部").add("ou", GetterUtil.getString(map.get("ou"))).build();
LdapNameBuilder ldapNameBuilder = LdapNameBuilder.newInstance();
if(StringUtils.isNotBlank(pou)) {
String[] ouPNameStr = pou.split(",");
for(String ouP:ouPNameStr) {
ldapNameBuilder.add("ou", ouP);
}
}
ldapNameBuilder.add("ou", GetterUtil.getString(map.get("ou")));
LdapName ldapName = ldapNameBuilder.build();
ldapTemplate.bind(ldapName,null, ouAttributes);
}
/**
* 新增用户
*/
@SneakyThrows
@Test
public void bingPerson() {
LdapName ldapName = LdapNameBuilder.newInstance().add("ou", "HR集团").add("cn", "LX011616").build();
// 基类设置
BasicAttribute ocattr = new BasicAttribute("objectClass");
ocattr.add("top");
ocattr.add("person");
ocattr.add("organizationalPerson");
ocattr.add("user");
// 用户属性
Attributes attrs = new BasicAttributes();
attrs.put(ocattr);
// 其他属性
attrs.put("cn", "LX011616");
attrs.put("displayName", "张宝宝");
attrs.put("givenName", "宝宝");
attrs.put("sn", "张");
attrs.put("userPassword", "qwe123+++");
// String newPassword = "qwe123+++";
// String newQuotedPassword = "\"" + newPassword + "\"";
// byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
// attrs.put("unicodePwd", newUnicodePassword.toString());
// attrs.put("userAccountControl", "544");
attrs.put("sAMAccountName", "LX011616");
attrs.put("userPrincipalName", "LX011616");
attrs.put("userAccountControl", Integer.toString(UF_NORMAL_ACCOUNT+UF_PASSWD_NOTREQD));
attrs.put("description", "HR集团");
ldapTemplate.bind(ldapName, null, attrs);
// LdapUser ldapUser = new LdapUser();
// ldapUser.setId(ldapName);
// ldapUser.setAccountName("LX011617");
// ldapUser.setCommonName("LX011617");
// ldapUser.setSurName("张");
// ldapUser.setGivenName("宝宝");
// ldapUser.setUserPassword("qwe123+++");
// ldapUser.setDisplayName("张宝宝");
// ldapUser.setUserAccountControl(Integer.toString(UF_NORMAL_ACCOUNT+UF_PASSWD_NOTREQD));
// ldapUser.setDescription("HR集团");
// ldapUser.setDepartment("HR集团");
// ldapTemplate.create(ldapUser);
}
private byte[] unicodePwd(String password) {
String newQuotedPassword = "\"" + password + "\"";
try {
byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
return newUnicodePassword;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
/**
* 新增用户
*/
@Test
public void savePerson() {
Map map = new HashMap<>();
map.put("cn","test");
map.put("sn","est");
map.put("displayName","test");
map.put("name","test");
map.put("userPassword","qwe123+++");
// map.put("userAccountControl", "514");
map.put("userAccountControl", "544");
map.put("department","事业部");
map.put("description","HR集团,事业部");
this.insertCn(map);
}
public void insertCn(Map map) {
Attributes ouAttributes=new BasicAttributes();
BasicAttribute ouBasicAttribute=new BasicAttribute("objectclass");
ouBasicAttribute.add("top");
ouBasicAttribute.add("person");
ouBasicAttribute.add("organizationalPerson");
ouBasicAttribute.add("user");
ouAttributes.put(ouBasicAttribute);
for(String str:map.keySet()){
if(StringUtils.isNotBlank(map.get(str))) {
ouAttributes.put(str,map.get(str));
}
}
// LdapName ldapName = LdapNameBuilder.newInstance().add("cn", GetterUtil.getString(map.get("cn"))).build();
LdapNameBuilder ldapNameBuilder = LdapNameBuilder.newInstance();
ldapNameBuilder.add("ou", "HR集团");
ldapNameBuilder.add("ou", "事业部");
ldapNameBuilder.add("cn", GetterUtil.getString(map.get("cn")));
LdapName ldapName = ldapNameBuilder.build();
ldapTemplate.bind(ldapName,null,ouAttributes);
}
/**
* 查找
*/
@Test
public void find() {
//精确查找
System.out.println(ldapTemplate.lookup("OU=HR集团"));
System.out.println(ldapTemplate.lookup("OU=HR集团", new LdapGroupAttributeMapper()));
}
/**
* 获取所有 internal人员
* ou=Internal,ou=People
*/
@Test
public void listUsers(){
AndFilter filter = new AndFilter();
filter.and(new EqualsFilter("objectClass", "person"));
filter.and(new WhitespaceWildcardsFilter("cn","LX"));
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
//查询所有内部人员
List users = ldapTemplate.search("ou=HR集团", filter.encode(), controls, new LdapPersonAttributeMapper());
// 默认 SUBTREE_SCOPE
// List users = ldapTemplate.search("ou=HR集团", filter.encode(), new LdapPersonAttributeMapper());
for (Person user: users ) {
System.out.println(JSON.toJSON(user));
}
}
/**
* 根据userid 查找单个人员
*/
@Test
public void findUser(){
DirContextAdapter obj = (DirContextAdapter) ldapTemplate.lookup("cn=test,ou=测试,ou=集团");//BASE_DC 不用填
System.out.println(obj);
}
/**
* 模糊查找
*/
@Test
public void findByName() {
LdapQuery query = LdapQueryBuilder.query()
.where("objectclass").is("person")
.and("cn").whitespaceWildcardsLike("测试");
ldapTemplate.search(query, nameClassPair -> {
// CN=测试api01,OU=用户,OU=总部
System.out.println(nameClassPair.getName());
// CN=测试api01,OU=用户,OU=总部,OU=集团,DC=inter-credit,DC=net
System.out.println(nameClassPair.getNameInNamespace());
// {samaccounttype=sAMAccountType: 805306368, primarygroupid=primaryGroupID: 513, objectclass=objectClass: top, person, organizationalPerson, user, badpasswordtime=badPasswordTime: 0, userpassword=userPassword: [B@71b1a49c, objectcategory=objectCategory: CN=Person,CN=Schema,CN=Configuration,DC=inter-credit,DC=net, cn=cn: 测试api01, useraccountcontrol=userAccountControl: 546, dscorepropagationdata=dSCorePropagationData: 16010101000000.0Z, codepage=codePage: 0, distinguishedname=distinguishedName: CN=测试api01,OU=用户,OU=总部,OU=集团,DC=inter-credit,DC=net, whenchanged=whenChanged: 20210729070624.0Z, whencreated=whenCreated: 20210729070624.0Z, pwdlastset=pwdLastSet: 0, logoncount=logonCount: 0, accountexpires=accountExpires: 9223372036854775807, lastlogoff=lastLogoff: 0, objectguid=objectGUID: g��D��A��s���, sn=sn: 测, lastlogon=lastLogon: 0, usnchanged=uSNChanged: 548575, usncreated=uSNCreated: 548574, objectsid=objectSid: �qL�,c�q.'� , countrycode=countryCode: 0, samaccountname=sAMAccountName: $M71000-0PD84RTVIFL7, instancetype=instanceType: 4, badpwdcount=badPwdCount: 0, name=name: 测试api01}
System.out.println(((SearchResult)nameClassPair).getAttributes());
});
}
/**
* 模糊查找
*/
@Test
public void findGroupByName() {
AndFilter filter = new AndFilter();
filter.and(new EqualsFilter("ou","市场组"));
LdapNameBuilder ldapNameBuilderQuery = LdapNameBuilder.newInstance();
ldapNameBuilderQuery.add("ou","HR集团");
LdapName ldapNameQuery = ldapNameBuilderQuery.build();
//查询所有内部人员
try {
List list = ldapTemplate.search(ldapNameQuery, filter.encode(), new LdapGroupAttributeMapper());
for (Group group: list ) {
System.out.println(JSON.toJSON(group));
}
} catch (Exception e) {
e.printStackTrace();
}
try {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
List groups = new ArrayList<>();
NamingEnumeration sr = ldapTemplate.getContextSource().getReadWriteContext().search(ldapNameQuery, filter.encode(), controls);
while(sr.hasMoreElements()){
Group group = new Group();
SearchResult result = sr.next();
NamingEnumeration extends Attribute> attrs = result.getAttributes().getAll();
while(attrs.hasMore()){
Attribute attr= attrs.next();
System.out.println(attr.getID() + "~~~~~~" + attr.get());
if("name".equals(attr.getID())){
group.setName( attr.get().toString());
}
if("cn".equals(attr.getID())){
group.setDepartmentCd( attr.get().toString());
}
if("description".equals(attr.getID())){
group.setDepartmentPName( attr.get().toString());
}
}
groups.add(group);
}
System.out.println(JSON.toJSON(groups));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 根据部门编号o,查找部门
*/
@Test
public void findDept(){
DirContextAdapter obj = (DirContextAdapter) ldapTemplate.lookup("ou=测试,ou=集团");//BASE_DC 不用填
System.out.println(obj);
}
@Test
public void rebingUser() {
Attributes ouAttributes=new BasicAttributes();
BasicAttribute ouBasicAttribute=new BasicAttribute("objectclass");
ouBasicAttribute.add("top");
ouBasicAttribute.add("person");
ouBasicAttribute.add("organizationalPerson");
ouBasicAttribute.add("user");
ouAttributes.put(ouBasicAttribute);
ouAttributes.put("cn", "LX011617");
ldapTemplate.rebind("cn=LX011617,ou=HR集团", null, ouAttributes);
}
/**
* 删除
*/
@Test
public void unbingUser() {
// ldapTemplate.unbind("cn=测试api01,ou=测试,ou=集团");
ldapTemplate.unbind("ou=市场组,ou=HR集团");
}
/**
* 修改信息
*/
@SneakyThrows
@Test
public void updateUser() {
String newPassword = "qwe123+++";
String newQuotedPassword = "\"" + newPassword + "\"";
byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
ldapTemplate.modifyAttributes("cn=LX011616,ou=HR集团", new ModificationItem[] {
// new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("cn", "")),
// new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("displayName", "")),
// new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("sn","")),
// new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("mail", "[email protected]")),
// new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("telephoneNumber", "")),
new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("userAccountControl", "512")),
// new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodePwd", newUnicodePassword.toString())) //需要ssl连接 https://docs.microsoft.com/zh-CN/troubleshoot/windows/win32/change-windows-active-directory-user-password
});
}
/**
* 修改信息
*/
@Test
public void modifyAttributes() {
DirContextOperations context = ldapTemplate
.lookupContext("cn=测试api01,ou=测试,ou=集团");
context.setAttributeValue("givenName", "测试");
ldapTemplate.modifyAttributes(context);
}
/**
* 重命名、移动
*/
@Test
public void rename() {
// ldapTemplate.rename("cn=LX011617,ou=HR集团", "cn=LX011617,ou=青岛,ou=HR集团");
ldapTemplate.rename("ou=测试test部门", "ou=测试test新部门");
}
}
实体类 LdapUser:
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.DnAttribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;
import javax.naming.Name;
@Entry(objectClasses = {"user", "organizationalPerson", "person", "top"})
public class LdapUser {
@Id
@JsonIgnore
private Name id;
@DnAttribute(value = "CN", index = 0)
@Attribute(name = "sAMAccountName")
private String accountName;
@Attribute(name = "cn")
private String commonName;
@Attribute(name = "sn")
private String surName;
@Attribute(name = "givenName")
private String givenName;
@Attribute(name = "distinguishedName")
private String dn;
@Attribute(name = "userPassword")
private String userPassword;
@Attribute(name = "displayName")
private String displayName;
@Attribute(name = "department")
private String department;
@Attribute(name = "userAccountControl")
private String userAccountControl;
@Attribute(name = "mobile")
private String mobile;
@Attribute(name = "mail")
private String email;
@Attribute(name = "description")
private String description;
//getter、settter .....
}
实现AttributesMapper只是从中获得所需的属性值Attributes并返回它。在内部,LdapTemplate遍历找到的所有条目,AttributesMapper为每个条目调用给定的条目,并将结果收集到列表中。
LdapGroupAttributeMapper:
import com.lxhr.ldap.pojo.Group;
import org.springframework.ldap.core.AttributesMapper;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
/**
* 将ldap返回的结果,转成指定对象
*/
public class LdapGroupAttributeMapper implements AttributesMapper {
@Override
public Group mapFromAttributes(Attributes attributes) throws NamingException {
Group group = new Group();
if(attributes.get("name") != null){
group.setName( attributes.get("name").get().toString());
}
if(attributes.get("cn") != null){
group.setDepartmentCd( attributes.get("cn").get().toString());
}
if(attributes.get("description") != null){
group.setDepartmentPName( attributes.get("description").get().toString());
}
return group;
}
}
LdapPersonAttributeMapper:
import com.lxhr.ldap.pojo.Person;
import org.springframework.ldap.core.AttributesMapper;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
/**
* 将ldap返回的结果,转成指定对象
*/
public class LdapPersonAttributeMapper implements AttributesMapper {
/**
* 将单个Attributes转成单个对象
* @param attrs
* @return
* @throws NamingException
*/
public Person mapFromAttributes(Attributes attrs) throws NamingException {
Person user = new Person();
if(attrs.get("uid") != null){
user.setUid( attrs.get("uid").get().toString());
}
if(attrs.get("cn") != null){
user.setCn( attrs.get("cn").get().toString());
}
if(attrs.get("sn") != null){
user.setSn( attrs.get("sn").get().toString());
}
if(attrs.get("name") != null){
user.setName( attrs.get("name").get().toString());
}
if(attrs.get("givenName") != null){
user.setGivenName( attrs.get("givenName").get().toString());
}
if(attrs.get("displayName") != null){
user.setDisplayName( attrs.get("displayName").get().toString());
}
if(attrs.get("company") != null){
user.setCompany( attrs.get("company").get().toString());
}
if(attrs.get("department") != null){
user.setDepartment( attrs.get("department").get().toString());
}
if(attrs.get("mobile") != null){
user.setMobile( attrs.get("mobile").get().toString());
}
if(attrs.get("mail") != null){
user.setMail( attrs.get("mail").get().toString());
}
if(attrs.get("distinguishedName") != null){
user.setDistinguishedName(attrs.get("distinguishedName").get().toString());
}
if(attrs.get("modifyTimestamp") != null){
user.setModifyTimestamp(attrs.get("modifyTimestamp").get().toString());
}
if(attrs.get("description") != null){
user.setDescription(attrs.get("description").get().toString());
}
return user;
}
}
Group:
import javax.naming.Name;
import java.io.Serializable;
public class Group implements Serializable {
private Name dn;
private String name;
private String departmentCd;
private String departmentName;
private String departmentPName;
//getter、setter ......
}
Person:
import javax.naming.Name;
import java.io.Serializable;
public class Person implements Serializable {
private Name dn;
private String uid;
private String cn;
//first name
private String givenName;
//last name
private String sn;
private String name;
private String displayName;
private String distinguishedName;
private String company;
private String department;
private String userPassword;
private String sAMAccountName;
private String userAccountControl;
private String userPrincipalName;
private String mail;
private String mobile;
private String description;
private String modifyTimestamp;
//getter、setter ......
}
如果想要通过 LDAP 更改 Windows Active Directory 和 LDS 用户密码,客户端必须具有到服务器的 128 位传输层安全性 (TLS) /Secure Socket Layer (SSL) 连接。
通过 LDAP Windows Active Directory 用户密码 - Application Developer | Microsoft Docs