mysql ldap 同步_将Ldap组织结构及用户信息同步到MySQL,用Spring Boot项目操作

从上一篇《将Mybatis引入Spring Boot项目连接数据库操作》知道了如何在Spring Boot项目操作数据库,学会了增删查改基本操作方法。本节记录如何从Ldap获取组织结构及用户信息并导入数据库。

一,引入Maven依赖并设置ldap连接信息

首先在pom.xml添加引入ldap依赖,如下所示:

org.springframework.boot

spring-boot-starter-data-ldap

保存后等待自动加载插件,加载完成后在application.properties配置文件中写目标ldap连接信息:

#目标ldap地址

spring.ldap.urls=ldap://192.168.10.168:389

#base是Base DN 即根节点

spring.ldap.base=DC=ldap,DC=local#指定用户的username是User DN即distinguishedName,可分辨名称、标识名称

spring.ldap.username=CN=Administrator,CN=Users,DC=ldap,DC=local#指定用户的密码

spring.ldap.password=这里写密码

上面是示例。如果不确定信息是否正确,可以用LDAPSoft Ldap Browser,AdminLdap等客户端工具连接测试。能正确加载组织结构及用户信息代表连接信息正确。保存配置。

二,从ldap获取数据的基础方法,用户及部门实体模型

在项目中新建package包,为了容易区分取名“LdapDemo”,在里面新建3个Class类,分别取名LdapPerson,LdapDepartment,LdapService。前两个是ldap用户信息实体模型和ldap部门信息实体模型,第3个是写获取数据等基础方法的Service。

LdapPerson.java代码如下:

packagexxh.springbootmvc.xxhdemo1.LdapDemo;public classLdapPerson {publicString getObjectClass() {returnobjectClass;

}public voidsetObjectClass(String objectClass) {this.objectClass =objectClass;

}publicString getCn() {returncn;

}public voidsetCn(String cn) {this.cn =cn;

}publicString getDisplayName() {returndisplayName;

}public voidsetDisplayName(String displayName) {this.displayName =displayName;

}publicString getsAMAccountName() {returnsAMAccountName;

}public voidsetsAMAccountName(String sAMAccountName) {this.sAMAccountName =sAMAccountName;

}publicString getSn() {returnsn;

}public voidsetSn(String sn) {this.sn =sn;

}publicString getGivenName() {returngivenName;

}public voidsetGivenName(String givenName) {this.givenName =givenName;

}publicString getObjectGUID() {returnobjectGUID;

}public voidsetObjectGUID(String objectGUID) {this.objectGUID =objectGUID;

}public booleanisDeleted() {returnisDeleted;

}public void setDeleted(booleandeleted) {

isDeleted=deleted;

}public booleanisPrivilegeHolder() {returnisPrivilegeHolder;

}public void setPrivilegeHolder(booleanprivilegeHolder) {

isPrivilegeHolder=privilegeHolder;

}public booleanisRecycled() {returnisRecycled;

}public void setRecycled(booleanrecycled) {

isRecycled=recycled;

}publicString getDistinguishedName() {returndistinguishedName;

}public voidsetDistinguishedName(String distinguishedName) {this.distinguishedName =distinguishedName;

}publicString getDescription() {returndescription;

}public voidsetDescription(String description) {this.description =description;

}private String objectClass; //organizationalPerson

private String cn; //名称、唯一标识

private String displayName; //显示名

private String sAMAccountName; //登录名(唯一标识)

private String sn; //姓

private String givenName; //名

privateString objectGUID;private boolean isDeleted; //删除的、禁用的

private boolean isPrivilegeHolder; //特权

private boolean isRecycled; //恢复的

private String distinguishedName; //DN

privateString description;

}

保存。

LdapDepartment.java代码如下:

packagexxh.springbootmvc.xxhdemo1.LdapDemo;public classLdapDepartment {publicString getObjectClass() {returnobjectClass;

}public voidsetObjectClass(String objectClass) {this.objectClass =objectClass;

}publicString getOu() {returnou;

}public voidsetOu(String ou) {this.ou =ou;

}publicString getObjectGUID() {returnobjectGUID;

}public voidsetObjectGUID(String objectGUID) {this.objectGUID =objectGUID;

}public booleanisDeleted() {returnisDeleted;

}public void setDeleted(booleandeleted) {

isDeleted=deleted;

}public booleanisPrivilegeHolder() {returnisPrivilegeHolder;

}public void setPrivilegeHolder(booleanprivilegeHolder) {

isPrivilegeHolder=privilegeHolder;

}public booleanisRecycled() {returnisRecycled;

}public void setRecycled(booleanrecycled) {

isRecycled=recycled;

}publicString getDistinguishedName() {returndistinguishedName;

}public voidsetDistinguishedName(String distinguishedName) {this.distinguishedName =distinguishedName;

}publicString getDescription() {returndescription;

}public voidsetDescription(String description) {this.description =description;

}private String objectClass; //organizationalUnit

private String ou; //名称、唯一标识

privateString objectGUID;private boolean isDeleted; //删除的、禁用的

private boolean isPrivilegeHolder; //特权

private boolean isRecycled; //恢复的

private String distinguishedName; //DN

privateString description;

}

LdapService.java代码如下:

packagexxh.springbootmvc.xxhdemo1.LdapDemo;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.ldap.core.AttributesMapper;importorg.springframework.ldap.core.LdapTemplate;importorg.springframework.stereotype.Service;importjavax.naming.NamingException;importjavax.naming.directory.Attributes;import java.io.*;importjava.util.List;import staticorg.springframework.ldap.query.LdapQueryBuilder.query;

@Servicepublic classLdapService {

@AutowiredprivateLdapTemplate ldapTemplate;//获取Ldap部门

public ListgetLdapDepartment(String objectClass,String DN) {if (null == objectClass || objectClass.length() < 1)

objectClass= "organizationalUnit";

System.out.println("getLdapDepartment> " + objectClass + "," +DN);

ldapTemplate.setIgnorePartialResultException(true);returnldapTemplate.search(

query().where("objectclass").is(objectClass)

.and("distinguishedName").like(DN),newLdapDepartmentAttributesMapper());

}//自定义序列化Ldap部门实体

private class LdapDepartmentAttributesMapper implements AttributesMapper{

@Overridepublic LdapDepartment mapFromAttributes(Attributes attrs) throwsNamingException {

LdapDepartment ldapDepartment= newLdapDepartment();if (null != attrs.get("objectClass")) {

ldapDepartment.setObjectClass((String) attrs.get("objectClass").get());

}if (null != attrs.get("ou")) {

ldapDepartment.setOu((String) attrs.get("ou").get());

}if (null != attrs.get("objectGUID")) {//将ldap的objectGUID转换成字符串

ldapDepartment.setObjectGUID(convertObjectGUID(attrs.get("objectGUID").get()));

}if (null != attrs.get("isDeleted")) {

ldapDepartment.setDeleted((boolean) attrs.get("isDeleted").get());

}if (null != attrs.get("isPrivilegeHolder")) {

ldapDepartment.setPrivilegeHolder((boolean) attrs.get("isPrivilegeHolder").get());

}if (null != attrs.get("isRecycled")) {

ldapDepartment.setRecycled((boolean) attrs.get("isRecycled").get());

}if (null != attrs.get("distinguishedName")) {

ldapDepartment.setDistinguishedName((String) attrs.get("distinguishedName").get());

}if (null != attrs.get("description")) {

ldapDepartment.setDescription((String) attrs.get("description").get());

}returnldapDepartment;

}

}//获取Ldap用户

public ListgetLdapPerson(String objectClass,String DN) {if(null==objectClass || objectClass.length()<1)

objectClass="organizationalPerson";

ldapTemplate.setIgnorePartialResultException(true);returnldapTemplate.search(

query().where("objectclass").is(objectClass)

.and("distinguishedName").is(DN),newLdapPersonAttributesMapper());

}//自定义序列化Ldap用户实体

private class LdapPersonAttributesMapper implements AttributesMapper{

@Overridepublic LdapPerson mapFromAttributes(Attributes attrs) throwsNamingException {

LdapPerson ldapPerson= newLdapPerson();if (null != attrs.get("objectClass")) {

ldapPerson.setObjectClass((String) attrs.get("objectClass").get());

}if (null != attrs.get("cn")) {

ldapPerson.setCn((String) attrs.get("cn").get());

}if (null != attrs.get("displayName")) {

ldapPerson.setDisplayName((String) attrs.get("displayName").get());

}if (null != attrs.get("sAMAccountName")) {

ldapPerson.setsAMAccountName((String) attrs.get("sAMAccountName").get());

}if (null != attrs.get("sn")) {

ldapPerson.setSn((String) attrs.get("sn").get());

}if (null != attrs.get("givenName")) {

ldapPerson.setGivenName((String) attrs.get("givenName").get());

}if (null != attrs.get("objectGUID")) {//将ldap的objectGUID转换成字符串

ldapPerson.setObjectGUID(convertObjectGUID(attrs.get("objectGUID").get()));

}if (null != attrs.get("isDeleted")) {

ldapPerson.setDeleted((boolean) attrs.get("isDeleted").get());

}if (null != attrs.get("isPrivilegeHolder")) {

ldapPerson.setPrivilegeHolder((boolean) attrs.get("isPrivilegeHolder").get());

}if (null != attrs.get("isRecycled")) {

ldapPerson.setRecycled((boolean) attrs.get("isRecycled").get());

}if (null != attrs.get("distinguishedName")) {

ldapPerson.setDistinguishedName((String) attrs.get("distinguishedName").get());

}if (null != attrs.get("description")) {

ldapPerson.setDescription((String) attrs.get("description").get());

}returnldapPerson;

}

}//示例:获取全部用户名

public ListgetAllPersonNames() {

ldapTemplate.setIgnorePartialResultException(true);returnldapTemplate.search(

query().where("objectclass").is("person"), (AttributesMapper) attrs -> (String) attrs.get("cn").get());

}//region 这里都是解决ldap获取数据中的objectGUID乱码问题,虽然解决了乱码但是值不一样,该值不建议当做标识使用。

/*** 对象转数组

*@paramobj

*@return

*/

private static byte[] toByteArray (Object obj) {byte[] bytes = null;

ByteArrayOutputStream bos= newByteArrayOutputStream();try{

ObjectOutputStream oos= newObjectOutputStream(bos);

oos.writeObject(obj);

oos.flush();

bytes=bos.toByteArray ();

oos.close();

bos.close();

}catch(IOException ex) {

ex.printStackTrace();

}returnbytes;

}/*** 数组转对象

*@parambytes

*@return

*/

private static Object toObject (byte[] bytes) {

Object obj= null;try{

ByteArrayInputStream bis= newByteArrayInputStream (bytes);

ObjectInputStream ois= newObjectInputStream (bis);

obj=ois.readObject();

ois.close();

bis.close();

}catch(IOException ex) {

ex.printStackTrace();

}catch(ClassNotFoundException ex) {

ex.printStackTrace();

}returnobj;

}private static String AddLeadingZero(intk) {return (k <= 0xF) ? "0" +Integer.toHexString(k) : Integer.toHexString(k);

}private staticString convertObjectGUID(Object ObjectGUID) {byte[] GUID =toByteArray(ObjectGUID);

String strGUID= "";

String byteGUID= "";//Convert the GUID into string using the byte format

for (int c = 0; c < GUID.length; c++) {

byteGUID= byteGUID + "\\" + AddLeadingZero((int) GUID[c] & 0xFF);

}//strGUID = "{";

strGUID = strGUID + AddLeadingZero((int) GUID[3] & 0xFF);

strGUID= strGUID + AddLeadingZero((int) GUID[2] & 0xFF);

strGUID= strGUID + AddLeadingZero((int) GUID[1] & 0xFF);

strGUID= strGUID + AddLeadingZero((int) GUID[0] & 0xFF);

strGUID= strGUID + "-";

strGUID= strGUID + AddLeadingZero((int) GUID[5] & 0xFF);

strGUID= strGUID + AddLeadingZero((int) GUID[4] & 0xFF);

strGUID= strGUID + "-";

strGUID= strGUID + AddLeadingZero((int) GUID[7] & 0xFF);

strGUID= strGUID + AddLeadingZero((int) GUID[6] & 0xFF);

strGUID= strGUID + "-";

strGUID= strGUID + AddLeadingZero((int) GUID[8] & 0xFF);

strGUID= strGUID + AddLeadingZero((int) GUID[9] & 0xFF);

strGUID= strGUID + "-";

strGUID= strGUID + AddLeadingZero((int) GUID[10] & 0xFF);

strGUID= strGUID + AddLeadingZero((int) GUID[11] & 0xFF);

strGUID= strGUID + AddLeadingZero((int) GUID[12] & 0xFF);

strGUID= strGUID + AddLeadingZero((int) GUID[13] & 0xFF);

strGUID= strGUID + AddLeadingZero((int) GUID[14] & 0xFF);

strGUID= strGUID + AddLeadingZero((int) GUID[15] & 0xFF);//strGUID = strGUID + "}";//System.out.println("GUID (String format): " + strGUID);//System.out.println("GUID (Byte format): " + byteGUID);

returnstrGUID;

}//endregion

}

Service里面方法实现可以参考下面几篇博客:

注意:

1,LdapService类前面要加@Service标注。

2,需要在类体声明LdapTemplate才能在方法里使用(在方法里面声明不行)。

@Autowired

private LdapTemplate ldapTemplate;

3,查询ldap组织结构及用户信息需要使用拉姆达表达式,具体请看上面代码示例。

三,调用LdapService获取数据并以接口形式输出显示

在项目里面创建Class类,命名为ldapTestController,在这里面写接口调用LdapService获取数据并以接口形式输出显示。如下:

packagexxh.springbootmvc.xxhdemo1.LdapDemo;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.autoconfigure.EnableAutoConfiguration;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;

@RestController

@EnableAutoConfiguration

@RequestMapping("/v1/ldapdemo")public classldapTestController {/*声明LdapService*/@AutowiredprivateLdapService ldapService;// http://localhost:8888/v1/ldapdemo/getPersonNameList

/*获取所有用户名称接口*/@RequestMapping("/getPersonNameList")publicObject queryPersonNameList() {returnldapService.getAllPersonNames();

}// http://localhost:8888/v1/ldapdemo/getLdapDepartmentList?objectclass=&dn=// http://localhost:8888/v1/ldapdemo/getLdapDepartmentList?objectclass=&dn=// http://localhost:8888/v1/ldapdemo/getLdapDepartmentList?dn=OU=%E8%BF%90%E8%90%A5%E6%9C%8D%E5%8A%A1%E9%83%A8,DC=ldap,DC=local

/*根据筛选获条件取部门接口*/@RequestMapping("/getLdapDepartmentList")publicObject queryLdapDepartmentList(String objectclass, String dn) {if (null == dn || dn.length() < 1)

dn= "OU=实施组,OU=运营服务部,DC=ldap,DC=local";returnldapService.getLdapDepartment(objectclass, dn);

}// http://localhost:8888/v1/ldapdemo/getLdapPersonList?dn=OU=实施组,OU=运营服务部,DC=ldap,DC=local

/*根据筛选获条件取用户接口*/@RequestMapping("/getLdapPersonList")publicObject queryLdapPersonList(String objectclass, String dn) {if (null == dn || dn.length() < 1)

dn= "CN=刘备,OU=实施组,OU=运营服务部,DC=ldap,DC=local";returnldapService.getLdapPerson(objectclass, dn);

}

}

我这里是直接用接口显示出来。其实真实项目中是录入到数据库里面。

本篇博客涉及到的项目文件及目录结构:

f2fc41963981c618f767b8c531c3efa5.png

四,接口效果截图

获取所有用户名称接口  效果如下:

0281875231c81a62e57e6ce88be0c1e5.png

根据筛选获条件取部门接口  效果如下:

4cda88b453cbf500df66a1bbcc6fa7a5.png

根据筛选获条件取用户接口  效果如下:

7fdce308e263a6b5824c2d724ebbde3a.png

本篇总结就写到这里了。

缺点:

1,虽然将Ldap的objectGUID能转换成字符串不再是乱码,但是值不等于Ldap里面的objectGUID值。所以不建议用它作为数据对比的标识。

2,本篇代码还不能按照友好的上下级关系一层一层往下查找(目前是查出所有的部门或用户,或者筛选已知部门或已知用户)。

下一篇:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值