Java对接OpenLdap实现数据单向同步到MySql
把配置信息写成配置项,优化代码:
最近公司项目需求有对接OpenLdap并连接MySql进行数据单向同步功能,公司里也是第一次对接,把任务交给了我,让我自行学习,并实现此功能。
在网上查阅许久,发现百分之80的博客皆是8年甚至更久远的文章,帮助并不大,Java对接OpenLdap实现数据单向同步到MySql的更是没有,所以我为了方便以后自己查阅,增强记忆,将代码以及方法贴出来。也希望能对大家有所帮助。
package com.tiduyun.cmp.biz.model.vo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import lombok.Data;
import lombok.ToString;
@Component
@Configuration
@ToString
@Data
/**
* @author huyuan@tiduyun.com
* OpenLdap服务连接信息
*/
public class OpenLdapConnectionVo {
@Value("${cmp.biz.ldap.host}")
private String ldapHots;
@Value("${cmp.biz.ldap.port}")
private String ldapPort;
@Value("${cmp.biz.ldap.bindDn}")
private String ldapBindDN;
@Value("${cmp.biz.ldap.password}")
private String ldapPassword;
@Value("${cmp.biz.ldap.baseDn}")
private String ldapBaseDN;
@Value("${cmp.biz.ldap.userDefaultPassword}")
private String userDefaultPassword;
@Value("${cmp.biz.ldap.tenantType}")
private Integer tenantType;
}
注:此代码适用于微服务,分布式架构,利于后期数据的更改以及维护的便利。单体架构可直接写入配置文件,在实现类中调用即可。
对应的配置文件:
注:userDefaultPassword , tenantType 这两个字段可忽略。如果不知道如何启动OpenLdap服务的小伙伴,可以到这个链接里学习一下,也是我查阅许多资料里,效果最好的一个博客,点击前往。
接下来回归正题,先说明一下每个字段的意思:
host:连接的IP(也是Java连接OpenLdap最重要的)
bindDn: 即OpenLdap配置文件里的自己配置的账号。
password: 见名知意
baseDn: 即OpenLdap配置文件里自己配置的名字(此处可以理解为MySql中数据库名字)
port: OpenLdap的端口(OpenLdap默认端口389)
导入依赖
<!-- https://mvnrepository.com/artifact/com.novell.ldap/jldap -->
<dependency>
<groupId>com.novell.ldap</groupId>
<artifactId>jldap</artifactId>
<version>4.3</version>
</dependency>
Spring也有Ldap,看个人喜好使用,我也把它贴上
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
<version>2.3.2.RELEASE</version>
</dependency>
Service
package com.tiduyun.cmp.biz.service;
/**
* @author huyuan@tiduyun.com
* ldapDataSynchronization LDAP数据同步
*/
public interface OpenLdapService {
void ldapDataSynchronization();
}
实现类(连接OpenLdap代码如下)
package com.tiduyun.cmp.biz.service.impl;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import com.tiduyun.cmp.biz.constant.ApplicationContextConstants;
import com.tiduyun.cmp.common.core.constant.IsDeleted;
import com.tiduyun.cmp.user.constant.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.novell.ldap.*;
import com.tiduyun.cmp.biz.model.vo.OpenLdapConnectionVo;
import com.tiduyun.cmp.biz.service.OpenLdapService;
import com.tiduyun.cmp.biz.service.TenantService;
import com.tiduyun.cmp.biz.service.UserAccountService;
import com.tiduyun.cmp.biz.service.UserService;
import com.tiduyun.cmp.common.core.constant.BuiltInUserId;
import com.tiduyun.cmp.common.model.user.Tenant;
import com.tiduyun.cmp.common.model.user.TenantOpenLdapLinkedData;
import com.tiduyun.cmp.common.model.user.User;
import com.tiduyun.cmp.common.model.user.UserAccount;
import com.tiduyun.cmp.user.client.OpenLdapManageClient;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class OpenLdapServiceImpl implements OpenLdapService {
@Resource
private OpenLdapConnectionVo openLdapConnectionVo;
@Override
public void ldapDataSynchronization() {
String searchFilter = "objectClass=*";
int ldapPort = LDAPConnection.DEFAULT_PORT;
int searchScope = LDAPConnection.SCOPE_SUB;
//查询Ldap数据存入数据库
LDAPConnection lc = new LDAPConnection();
try {
lc.connect(openLdapConnectionVo.getLdapHots(), ldapPort);
lc.bind(LDAPConnection.LDAP_V3, openLdapConnectionVo.getLdapBindDN(),
openLdapConnectionVo.getLdapPassword().getBytes("UTF8"));
LDAPSearchResults searchResults = lc.search(openLdapConnectionVo.getLdapBaseDN(), searchScope, searchFilter, null,
false);
while (searchResults.hasMore()) {
LDAPEntry nextEntry = null;
try {
nextEntry = searchResults.next();
} catch (LDAPException e) {
log.error("LDAP服务器连接失败 : " , e);
if (e.getResultCode() == LDAPException.LDAP_TIMEOUT || e.getResultCode() == LDAPException.CONNECT_ERROR) {
break;
} else {
continue;
}
}
}
Java连接OpenLdap将其数据同步至MySql,实现类完整代码如下(上条代码为连接代码)
package com.tiduyun.cmp.biz.service.impl;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import com.tiduyun.cmp.biz.constant.ApplicationContextConstants;
import com.tiduyun.cmp.common.core.constant.IsDeleted;
import com.tiduyun.cmp.user.constant.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.novell.ldap.*;
import com.tiduyun.cmp.biz.model.vo.OpenLdapConnectionVo;
import com.tiduyun.cmp.biz.service.OpenLdapService;
import com.tiduyun.cmp.biz.service.TenantService;
import com.tiduyun.cmp.biz.service.UserAccountService;
import com.tiduyun.cmp.biz.service.UserService;
import com.tiduyun.cmp.common.core.constant.BuiltInUserId;
import com.tiduyun.cmp.common.model.user.Tenant;
import com.tiduyun.cmp.common.model.user.TenantOpenLdapLinkedData;
import com.tiduyun.cmp.common.model.user.User;
import com.tiduyun.cmp.common.model.user.UserAccount;
import com.tiduyun.cmp.user.client.OpenLdapManageClient;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class OpenLdapServiceImpl implements OpenLdapService {
//租户常量
private final static byte isDel = IsDeleted.NO;
private final static String tenantStatus = TenantStatus.AVAILABLE;
//用户常量
private final static int userType = UserType.TENANT_USER;
private final static int userStatus = UserStatus.NORMAL;
private final static int accountStatus = UserAccountStatus.NORMAL;
private final static int accountType = UserAccountType.ADMIN_USER_NORMAL;
@Resource
private OpenLdapConnectionVo openLdapConnectionVo;
@Autowired
private UserService userService;
@Autowired
private TenantService tenantService;
@Autowired
private UserAccountService userAccountService;
@Autowired
private OpenLdapManageClient openLdapManageClient;
private User systemOperatorUser;
@PostConstruct
public void initService() {
systemOperatorUser = new User();
systemOperatorUser.setId(BuiltInUserId.SYSTEM_OPERATOR_USER_ID);
systemOperatorUser.setType(UserType.ADMIN_USER);
systemOperatorUser.setTenantId(ApplicationContextConstants.ADMIN_USER_TENANT_ID);
systemOperatorUser.setTopTenantId(ApplicationContextConstants.ADMIN_USER_TENANT_ID);
}
@Override
public void ldapDataSynchronization() {
String searchFilter = "objectClass=*";
int ldapPort = LDAPConnection.DEFAULT_PORT;
int searchScope = LDAPConnection.SCOPE_SUB;
//查询Ldap数据存入数据库
LDAPConnection lc = new LDAPConnection();
try {
lc.connect(openLdapConnectionVo.getLdapHots(), ldapPort);
lc.bind(LDAPConnection.LDAP_V3, openLdapConnectionVo.getLdapBindDN(),
openLdapConnectionVo.getLdapPassword().getBytes("UTF8"));
LDAPSearchResults searchResults = lc.search(openLdapConnectionVo.getLdapBaseDN(), searchScope, searchFilter, null,
false);
while (searchResults.hasMore()) {
LDAPEntry nextEntry = null;
try {
nextEntry = searchResults.next();
} catch (LDAPException e) {
log.error("LDAP服务器连接失败 : " , e);
if (e.getResultCode() == LDAPException.LDAP_TIMEOUT || e.getResultCode() == LDAPException.CONNECT_ERROR) {
break;
} else {
continue;
}
}
String ldapId = nextEntry.getDN();
String string = ldapId.replaceAll("=", "':'").replaceAll(",", "','");
String s = "{'"+string+"'}";
JSONObject jsonObject= JSON.parseObject(s);
String uid = (String)jsonObject.get("uid");
if(StringUtils.isEmpty(uid)){
continue;
}
String ldapType = (String)jsonObject.get("ou");
TenantOpenLdapLinkedData ldapData=new TenantOpenLdapLinkedData();
ldapData.setLdapId(ldapId);
ldapData.setLdapType(uid);
ldapData.setTargetType(ldapType);
ldapData.setCreationTime(new Date());
ldapData.setUpdateTime(new Date());
LDAPAttributeSet attributeSet = nextEntry.getAttributeSet();
Object cn = attributeSet.getAttribute("cn");
ldapData.setTargetName(getLdapDataByKey(cn));
Object sn = attributeSet.getAttribute("sn");
Integer snInt = Integer.parseInt(getLdapDataByKey(sn));
TenantOpenLdapLinkedData LinkedData = openLdapManageClient.getLdapData(snInt);
Object ObejectO = attributeSet.getAttribute("o");
String o = getLdapDataByKey(ObejectO);
if(null ==LinkedData){
ldapData.setTargetId(snInt);
ldapData.setTenantId(Integer.parseInt(o));
openLdapManageClient.insertSelective(ldapData);
}
}
} catch (LDAPException e) {
log.error("Ldap error data : " , e);
} catch (UnsupportedEncodingException e) {
log.error("error message : " , e);
} finally {
try {
if (lc.isConnected()) {
lc.disconnect();
}
} catch (Exception e) {
log.error("parse error data : " , e);
}
}
//Ldap租户数据同步
List<TenantOpenLdapLinkedData> tenantList = openLdapManageClient.selectLdapByType("Tenant");
for(TenantOpenLdapLinkedData ldapTenant:tenantList){
String targetName = ldapTenant.getTargetName();
Tenant tenant = openLdapManageClient.getTenantByTenantName(targetName);
if(null==tenant){
Tenant t=new Tenant();
String ldapTargetName = ldapTenant.getTargetName();
t.setName(ldapTargetName);
t.setStatus(tenantStatus);
t.setCreatorUserId(systemOperatorUser.getId());
t.setType(openLdapConnectionVo.getTenantType());
Tenant tenant1 = tenantService.addTenant(systemOperatorUser,t);
Integer id = tenant1.getId();
t.setId(id);
t.setTopTenantId(id);
openLdapManageClient.updateByPrimaryKeySelective(t);
}
}
//LDAP用户数据同步
List<TenantOpenLdapLinkedData> userList = openLdapManageClient.selectLdapByType("User");
for(TenantOpenLdapLinkedData userTenant:userList){
String name = userTenant.getTargetName();
User user = openLdapManageClient.getUserByTargetName(name);
if(null==user){
User u=new User();
Date date = new Date();
String userTargetName = userTenant.getTargetName();
Integer targetId = userTenant.getTargetId();
//通过这个id去查询tenant的主键
String targetNameById = openLdapManageClient.getTargetNameById(targetId);
String idByName = openLdapManageClient.getIdByName(targetNameById);
if(StringUtils.isEmpty(idByName)){
idByName="0";
}
int id=Integer.parseInt(idByName);
u.setName(userTargetName);
//LDAP数据同步用户默认值的设置
u.setStatus(userStatus);
u.setType(userType);
u.setTopTenantId(id);
u.setTenantId(id);
u.setName(userTenant.getTargetName());
u.setIsDeleted(isDel);
u.setCreationTime(date);
User user1 = userService.addTenantUser(u);
//user_account表数据默认值
UserAccount userAccount=new UserAccount();
userAccount.setStatus(accountStatus);
userAccount.setType(accountType);
userAccount.setIsDeleted(isDel);
userAccount.setPassword(openLdapConnectionVo.getUserDefaultPassword());
userAccount.setCreationTime(date);
//user_account数据
userAccount.setUserId(user1.getId());
userAccount.setName(userTenant.getTargetName());
userAccountService.addUserAccount(userAccount);
}
}
}
public String getLdapDataByKey(Object o){
String snString = o.toString();
String pathone= snString.substring(snString.indexOf("value"));
String snStringone = pathone.replaceAll("=", "':");
JSONObject snJson = JSON.parseObject("{'" + snStringone);
return snJson.get("value").toString();
}
}
此方法为四张表关联,主要提供思路。其中的实体类,工具类等等我就不贴出来了,小伙伴们自行更改。如只需要连接OpenLdap,可以直接使用连接OpenLdap的代码,再加上你自己的方法即可。如需要连接数据库进行操作,可参考完整代码,进行更改。
以上就是Java连接OpenLdap同步其数据到MySql的方法,有许多不足欢迎指出更正,希望能对大家有帮助。