Browse Source

域控修改 账号查询改为redis中获取

master
DouDou 4 months ago
parent
commit
62a32b2be6
  1. 98
      src/main/java/com/spring/common/utils/LdapReadUtils.java
  2. 83
      src/main/java/com/spring/config/LdapAccountInitLoad.java
  3. 143
      src/main/java/com/spring/modules/sys/service/impl/CheckLdapDirectoryImpl.java
  4. 75
      src/main/java/com/spring/modules/sys/task/LdapAccountRefreshTask.java
  5. 1
      src/main/resources/application-dev.yml

98
src/main/java/com/spring/common/utils/LdapReadUtils.java

@ -0,0 +1,98 @@
package com.spring.common.utils;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.PartialResultException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.PagedResultsControl;
import javax.naming.ldap.PagedResultsResponseControl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @ClassName: LdapReadUtils
* @Description: 读取数据
* @author: LR
* @date: 2025年9月5日 下午12:04:30
* @Copyright:
*/
public class LdapReadUtils {
private static final Logger logger = LoggerFactory.getLogger(LdapReadUtils.class);
/**
*
* @Title: getAllLdapAccount
* @Description: 查询所有域控行号 通过分页查询来做
* @author: LR
* @date 2025年9月5日 下午12:07:09
* @return: Map<String,String>
*/
public static Map<String, String> getAllLdapAccount(LdapContext ctx, String ldapBase) throws NamingException, IOException {
byte[] cookie = null;
// 设置返回所有属性
SearchControls controls = new SearchControls();
controls.setReturningAttributes(new String[] {
"sAMAccountName", "displayName", "distinguishedName", "manager"
});
controls.setSearchScope(SearchControls.SUBTREE_SCOPE); //
String nameFilter = "(&(objectClass=user)(objectCategory=person)(!(objectClass=computer)))";
Map<String, String> ldapAccountMap = new HashMap<>();
//循环执行
do{
ctx.setRequestControls(new Control[]
{new PagedResultsControl(100, cookie, true)});
NamingEnumeration<SearchResult> results = null;
try{
results = ctx.search(ldapBase, nameFilter, controls);
//获取数据 读取人员组织架构+域控账号
while (results.hasMore()) {
SearchResult result = results.next();
Attributes attrs = result.getAttributes();
String distinguishedName = attrs.get("distinguishedName").get().toString();
String sAMAccountName = attrs.get("sAMAccountName").get().toString();
logger.info("distinguishedName:"+distinguishedName);
logger.info("sAMAccountName:"+sAMAccountName);
ldapAccountMap.put(distinguishedName, sAMAccountName);
}
}catch(PartialResultException pre){
logger.warn("Search results: {}", pre.getMessage());
}finally{
ctx.setRequestControls(null);
}
// 处理服务器返回的分页响应
Control[] controlsResp = ctx.getResponseControls();
if (controlsResp != null) {
for (Control control : controlsResp) {
if (control instanceof PagedResultsResponseControl) {
PagedResultsResponseControl prrc = (PagedResultsResponseControl) control;
cookie = prrc.getCookie();
}
}
} else {
cookie = null;
}
}while(cookie != null && cookie.length > 0);
//返回结果数据
return ldapAccountMap;
}
}

83
src/main/java/com/spring/config/LdapAccountInitLoad.java

@ -0,0 +1,83 @@
package com.spring.config;
import java.util.Map;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import com.spring.common.utils.LdapReadUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
/**
*
* @ClassName: LdapAccountInitLoad
* @Description: 聚水潭权限数据加载
* @author: LR
* @date: 2022年11月25日 下午2:50:56
* @Copyright:
*/
@Component
@Order(value = 12)
public class LdapAccountInitLoad implements ApplicationRunner{
private static final Logger logger = LoggerFactory.getLogger(LdapAccountInitLoad.class);
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Value("${spring.ldap.urls}")
private String ldapUrl;
@Value("${spring.ldap.base}")
private String ldapBase;
@Value("${spring.ldap.username}")
private String ldapUserDn;
@Value("${spring.ldap.password}")
private String ldapPassword;
@Override
public void run(ApplicationArguments args) throws Exception {
//首先查询域控账号的所有数据
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapUrl);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, ldapUserDn);
env.put(Context.SECURITY_CREDENTIALS, ldapPassword);
env.put(Context.REFERRAL, "ignore");
env.put("ignorepartialresultexception", "true");
LdapContext ctx = null;
//尝试解析数据
try{
// 创建DirContext对象建立与LDAP服务器的连接
ctx = new InitialLdapContext(env, null);
//调用方法读取数据
Map<String, String> ldapAccountMap = LdapReadUtils.getAllLdapAccount(ctx, ldapBase);
// 数据放到redis中去
redisTemplate.opsForHash().putAll("ldapAccount", ldapAccountMap);
logger.info("域控账号缓存的数量:"+ldapAccountMap.size());
} catch (NamingException e) {
logger.error("Failed to connect to the LDAP server.");
} finally{
ctx.close();
}
}
}

143
src/main/java/com/spring/modules/sys/service/impl/CheckLdapDirectoryImpl.java

@ -1,7 +1,11 @@
package com.spring.modules.sys.service.impl;
import com.spring.modules.sys.service.CheckLdapDirectory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.naming.Context;
@ -25,6 +29,8 @@ import java.util.stream.Collectors;
*/
@Service
public class CheckLdapDirectoryImpl implements CheckLdapDirectory {
private static final Logger logger = LoggerFactory.getLogger(CheckLdapDirectoryImpl.class);
@Value("${spring.ldap.urls}")
private String ldapUrl;
@ -34,6 +40,9 @@ public class CheckLdapDirectoryImpl implements CheckLdapDirectory {
private String ldapUserDn;
@Value("${spring.ldap.password}")
private String ldapPassword;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public boolean checkUserLdapDirectory(String username, String directoryPath) throws NamingException {
@ -132,16 +141,6 @@ public class CheckLdapDirectoryImpl implements CheckLdapDirectory {
//返回的数据
Map<String, String> ldapGroupAccount = new HashMap<String, String>();
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapUrl);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, ldapUserDn);
env.put(Context.SECURITY_CREDENTIALS, ldapPassword);
// 创建DirContext对象建立与LDAP服务器的连接
DirContext ctx = new InitialDirContext(env);
AclFileAttributeView aclView = Files.getFileAttributeView(securityPath, AclFileAttributeView.class);
try {
aclView.getAcl().forEach(aclEntry -> {
@ -155,11 +154,23 @@ public class CheckLdapDirectoryImpl implements CheckLdapDirectory {
} catch (IOException e) {
throw new RuntimeException(e);
}
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapUrl);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, ldapUserDn);
env.put(Context.SECURITY_CREDENTIALS, ldapPassword);
// 创建DirContext对象建立与LDAP服务器的连接
DirContext ctx = new InitialDirContext(env);
Map<String, String> ldapAccount = new HashMap<String, String>();
if (ldapGroupAccount.size() > 0) {
//循环检查数据是否存在组信息 如果存在 需要把组数据 替换成账号的信息
for(String strKey : ldapGroupAccount.keySet()) {
if (checkMemberIsGroupWithName(ctx, strKey)){
System.out.println("新Group:"+strKey);
ldapAccount.putAll(getLdapAccountListFromGroup(ctx, strKey));
}else {
ldapAccount.put(strKey, strKey);
@ -192,6 +203,118 @@ public class CheckLdapDirectoryImpl implements CheckLdapDirectory {
NamingEnumeration<? extends Attribute> attrEnum = attrs.getAll();
while (attrEnum.hasMore()) {
Attribute attr = attrEnum.next();
// 处理多值属性
NamingEnumeration<?> values = attr.getAll();
while (values.hasMore()) {
Object value = values.next();
String valueStr = value.toString();
String currentMember = valueStr.substring(valueStr.indexOf("=")+1, valueStr.indexOf(","));
//从redis中获取数据
Object ldapAccountObj = redisTemplate.opsForHash().get("ldapAccount", valueStr);
//如果redis中存在 说明是账号
if(null != ldapAccountObj){
//设置Redis中的域控账号
String ldapAccount = String.valueOf(ldapAccountObj);
accountMap.put(ldapAccount, ldapAccount);
}else if (checkMemberIsGroup(ctx, valueStr)){
//递归调用
accountMap.putAll(getLdapAccountListFromGroup(ctx, currentMember));
}else {
logger.error("异常张哈信息:"+valueStr);
//accountMap.put(getLdapAccountByMemberStr(ctx, valueStr), currentMember);
}
}
}
}
return accountMap;
}
/**
*
* @return
* @throws NamingException
* @throws 查询用列表
*/
public Map<String, String> getLdapAccountListPage() throws NamingException {
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapUrl);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, ldapUserDn);
env.put(Context.SECURITY_CREDENTIALS, ldapPassword);
// 创建DirContext对象建立与LDAP服务器的连接
DirContext ctx = new InitialDirContext(env);
Map<String, String> accountMap = new HashMap<>();
// 设置返回所有属性
SearchControls controls = new SearchControls();
controls.setReturningAttributes(new String[] {
"ou", "cn", "distinguishedName", "description",
"name", "displayName", "objectClass"
});
controls.setSearchScope(SearchControls.ONELEVEL_SCOPE); // 只查询一级子OU
String nameFilter = "(objectClass=organizationalUnit)";
// 执行查询
NamingEnumeration<SearchResult> results = ctx.search(ldapBase, nameFilter, controls);
while (results.hasMore()) {
SearchResult result = results.next();
Attributes attrs = result.getAttributes();
NamingEnumeration<? extends Attribute> attrEnum = attrs.getAll();
while (attrEnum.hasMore()) {
Attribute attr = attrEnum.next();
// 处理多值属性
NamingEnumeration<?> values = attr.getAll();
while (values.hasMore()) {
Object value = values.next();
String valueStr = value.toString();
String currentMember = valueStr.substring(valueStr.indexOf("=")+1, valueStr.indexOf(","));
if (checkMemberIsGroup(ctx, valueStr)){
//递归调用
accountMap.putAll(getLdapAccountListFromGroup(ctx, currentMember));
}else {
accountMap.put(getLdapAccountByMemberStr(ctx, valueStr), currentMember);
}
}
}
}
return accountMap;
}
/**
*
* @param ctx
* @param groupDn
* @desc 新调试方法
* @throws NamingException
*/
public Map<String, String> getLdapAccountListFromGroupNew(DirContext ctx, String groupDn) throws NamingException {
Map<String, String> accountMap = new HashMap<>();
// 第一步直接搜索组内的所有用户一次性获取域账号
SearchControls userControls = new SearchControls();
userControls.setReturningAttributes(new String[] {"sAMAccountName", "cn", "distinguishedName"});
userControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// 查询直接属于该组的用户
String userFilter = "(&(objectClass=user)(memberOf=CN=" + groupDn + "," + ldapBase + "))";
// 执行查询
NamingEnumeration<SearchResult> userResults = ctx.search(ldapBase, userFilter, userControls);
while (userResults.hasMore()) {
SearchResult result = userResults.next();
Attributes attrs = result.getAttributes();
Attribute samAttr = attrs.get("sAMAccountName");
Attribute cnAttr = attrs.get("cn");
System.out.println(samAttr+","+cnAttr);
NamingEnumeration<? extends Attribute> attrEnum = attrs.getAll();
while (attrEnum.hasMore()) {
Attribute attr = attrEnum.next();
// 处理多值属性

75
src/main/java/com/spring/modules/sys/task/LdapAccountRefreshTask.java

@ -0,0 +1,75 @@
package com.spring.modules.sys.task;
import com.spring.common.utils.LdapReadUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;
/**
* 定时同步域控账号信息到 Redis
*/
@Component
@EnableScheduling
public class LdapAccountRefreshTask {
private static final Logger logger = LoggerFactory.getLogger(LdapAccountRefreshTask.class);
@Value("${spring.ldap.urls}")
private String ldapUrl;
@Value("${spring.ldap.base}")
private String ldapBase;
@Value("${spring.ldap.username}")
private String ldapUserDn;
@Value("${spring.ldap.password}")
private String ldapPassword;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Scheduled(cron = "${task.data.refreshLdapAccountToRedis}")
public void refreshLdapAccountToRedis() throws NamingException {
//首先查询域控账号的所有数据
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapUrl);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, ldapUserDn);
env.put(Context.SECURITY_CREDENTIALS, ldapPassword);
env.put(Context.REFERRAL, "ignore");
LdapContext ctx = null;
//尝试解析数据
try{
// 创建DirContext对象建立与LDAP服务器的连接
ctx = new InitialLdapContext(env, null);
//调用方法读取数据
Map<String, String> ldapAccountMap = LdapReadUtils.getAllLdapAccount(ctx, ldapBase);
// 数据放到redis中去
redisTemplate.opsForHash().putAll("ldapAccount", ldapAccountMap);
} catch (NamingException | IOException e) {
logger.error("Failed to connect to the LDAP server.");
} finally{
if (null != ctx){
ctx.close();
}
}
}
}

1
src/main/resources/application-dev.yml

@ -102,6 +102,7 @@ task:
syncLocationToPLM: 0 0 0 29 2 ? # 每4年执行
sync_part_catalog_to_plm: 0 0 0 29 2 ? # 每1分钟执行
syncInventoryPartToPlm: 0 0 0 29 2 ? # 每4年执行
refreshLdapAccountToRedis: 0 0 0 * * ? #
flag: false
# 单点登录

Loading…
Cancel
Save