ldap登录
This commit is contained in:
白书科技
2023-09-01 03:48:39 +00:00
parent 069c3e4cc9
commit d5e410cb1f
30 changed files with 1292 additions and 89 deletions

View File

@@ -35,4 +35,11 @@ public class ConfigConstant {
public static final String MINIO_BUCKET = "minio.bucket";
public static final String MINIO_ENDPOINT = "minio.endpoint";
public static final String MINIO_DOMAIN = "minio.domain";
public static final String LDAP_ENABLED = "ldap.enabled";
public static final String LDAP_URL = "ldap.url";
public static final String LDAP_ADMIN_USER = "ldap.admin_user";
public static final String LDAP_ADMIN_PASS = "ldap.admin_pass";
public static final String LDAP_BASE_DN = "ldap.base_dn";
public static final String LDAP_USER_DN_PREFIX = "ldap.user_dn_prefix";
}

View File

@@ -31,6 +31,7 @@ public class FrontendConstant {
add("/api/v1/system/config");
add("/api/v1/system/image-captcha");
add("/api/v1/auth/login/password");
add("/api/v1/auth/login/ldap");
}
};

View File

@@ -0,0 +1,244 @@
/*
* Copyright (C) 2023 杭州白书科技有限公司
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.playedu.common.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
/**
* @TableName ldap_user
*/
@TableName(value = "ldap_user")
public class LdapUser implements Serializable {
/** */
@TableId(type = IdType.AUTO)
private Integer id;
/** 唯一特征值 */
private String uuid;
/** 用户ID */
private Integer userId;
/** cn */
private String cn;
/** dn */
private String dn;
/** ou */
private String ou;
/** uid */
private String uid;
/** 邮箱 */
private String email;
/** */
private Date createdAt;
/** */
private Date updatedAt;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
/** */
public Integer getId() {
return id;
}
/** */
public void setId(Integer id) {
this.id = id;
}
/** 唯一特征值 */
public String getUuid() {
return uuid;
}
/** 唯一特征值 */
public void setUuid(String uuid) {
this.uuid = uuid;
}
/** 用户ID */
public Integer getUserId() {
return userId;
}
/** 用户ID */
public void setUserId(Integer userId) {
this.userId = userId;
}
/** cn */
public String getCn() {
return cn;
}
/** cn */
public void setCn(String cn) {
this.cn = cn;
}
/** dn */
public String getDn() {
return dn;
}
/** dn */
public void setDn(String dn) {
this.dn = dn;
}
/** ou */
public String getOu() {
return ou;
}
/** ou */
public void setOu(String ou) {
this.ou = ou;
}
/** uid */
public String getUid() {
return uid;
}
/** uid */
public void setUid(String uid) {
this.uid = uid;
}
/** 邮箱 */
public String getEmail() {
return email;
}
/** 邮箱 */
public void setEmail(String email) {
this.email = email;
}
/** */
public Date getCreatedAt() {
return createdAt;
}
/** */
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
/** */
public Date getUpdatedAt() {
return updatedAt;
}
/** */
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
@Override
public boolean equals(Object that) {
if (this == that) {
return true;
}
if (that == null) {
return false;
}
if (getClass() != that.getClass()) {
return false;
}
LdapUser other = (LdapUser) that;
return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
&& (this.getUuid() == null
? other.getUuid() == null
: this.getUuid().equals(other.getUuid()))
&& (this.getUserId() == null
? other.getUserId() == null
: this.getUserId().equals(other.getUserId()))
&& (this.getCn() == null
? other.getCn() == null
: this.getCn().equals(other.getCn()))
&& (this.getDn() == null
? other.getDn() == null
: this.getDn().equals(other.getDn()))
&& (this.getOu() == null
? other.getOu() == null
: this.getOu().equals(other.getOu()))
&& (this.getUid() == null
? other.getUid() == null
: this.getUid().equals(other.getUid()))
&& (this.getEmail() == null
? other.getEmail() == null
: this.getEmail().equals(other.getEmail()))
&& (this.getCreatedAt() == null
? other.getCreatedAt() == null
: this.getCreatedAt().equals(other.getCreatedAt()))
&& (this.getUpdatedAt() == null
? other.getUpdatedAt() == null
: this.getUpdatedAt().equals(other.getUpdatedAt()));
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
result = prime * result + ((getUuid() == null) ? 0 : getUuid().hashCode());
result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode());
result = prime * result + ((getCn() == null) ? 0 : getCn().hashCode());
result = prime * result + ((getDn() == null) ? 0 : getDn().hashCode());
result = prime * result + ((getOu() == null) ? 0 : getOu().hashCode());
result = prime * result + ((getUid() == null) ? 0 : getUid().hashCode());
result = prime * result + ((getEmail() == null) ? 0 : getEmail().hashCode());
result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode());
result = prime * result + ((getUpdatedAt() == null) ? 0 : getUpdatedAt().hashCode());
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", id=").append(id);
sb.append(", uuid=").append(uuid);
sb.append(", userId=").append(userId);
sb.append(", cn=").append(cn);
sb.append(", dn=").append(dn);
sb.append(", ou=").append(ou);
sb.append(", uid=").append(uid);
sb.append(", email=").append(email);
sb.append(", createdAt=").append(createdAt);
sb.append(", updatedAt=").append(updatedAt);
sb.append(", serialVersionUID=").append(serialVersionUID);
sb.append("]");
return sb.toString();
}
}

View File

@@ -15,7 +15,7 @@
*/
package xyz.playedu.common.exception;
public class ServiceException extends Exception {
public class ServiceException extends RuntimeException {
public ServiceException() {}
public ServiceException(String message) {

View File

@@ -0,0 +1,27 @@
/*
* Copyright (C) 2023 杭州白书科技有限公司
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.playedu.common.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import xyz.playedu.common.domain.LdapUser;
/**
* @author tengyongzhi
* @description 针对表【ldap_user】的数据库操作Mapper
* @createDate 2023-08-31 14:33:19 @Entity xyz.playedu.common.domain.LdapUser
*/
public interface LdapUserMapper extends BaseMapper<LdapUser> {}

View File

@@ -35,4 +35,8 @@ public interface AppConfigService extends IService<AppConfig> {
Map<String, String> keyValues();
MinioConfig getMinioConfig();
boolean enabledLdapLogin();
String defaultAvatar();
}

View File

@@ -45,7 +45,7 @@ public interface DepartmentService extends IService<Department> {
String childrenParentChain(Department department);
void create(String name, Integer parentId, Integer sort) throws NotFoundException;
Integer create(String name, Integer parentId, Integer sort) throws NotFoundException;
void remoteRelateUsersByDepId(Integer depId);
@@ -64,4 +64,6 @@ public interface DepartmentService extends IService<Department> {
Map<Integer, Integer> getDepartmentsUserCount();
List<Department> chunk(List<Integer> ids);
Integer createWithChainList(List<String> ou);
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2023 杭州白书科技有限公司
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.playedu.common.service;
import com.baomidou.mybatisplus.extension.service.IService;
import xyz.playedu.common.domain.LdapUser;
import xyz.playedu.common.util.ldap.LdapTransformUser;
/**
* @author tengyongzhi
* @description 针对表【ldap_user】的数据库操作Service
* @createDate 2023-08-31 11:59:27
*/
public interface LdapUserService extends IService<LdapUser> {
LdapUser findByUUID(String id);
LdapUser store(LdapTransformUser ldapTransformUser);
void updateUserId(Integer id, Integer userId);
void updateCN(Integer id, String cn);
void updateOU(Integer id, String newOU);
void updateEmail(Integer id, String email);
void updateUid(Integer id, String uid);
}

View File

@@ -80,4 +80,10 @@ public interface UserService extends IService<User> {
Map<Integer, List<Integer>> getDepIdsGroup(List<Integer> userIds);
void changeAvatar(Integer userId, String avatar);
void updateName(Integer id, String cn);
void updateDepId(Integer id, Integer[] depIds);
void updateEmail(Integer id, String email);
}

View File

@@ -81,7 +81,7 @@ public class AppConfigServiceImpl extends ServiceImpl<AppConfigMapper, AppConfig
});
});
if (list.size() > 0) {
if (!list.isEmpty()) {
updateBatchById(list);
}
}
@@ -103,4 +103,18 @@ public class AppConfigServiceImpl extends ServiceImpl<AppConfigMapper, AppConfig
minioConfig.setDomain(config.get(ConfigConstant.MINIO_DOMAIN));
return minioConfig;
}
@Override
public boolean enabledLdapLogin() {
AppConfig appConfig =
getOne(query().getWrapper().eq("key_name", ConfigConstant.LDAP_ENABLED));
return "1".equals(appConfig.getKeyValue());
}
@Override
public String defaultAvatar() {
AppConfig appConfig =
getOne(query().getWrapper().eq("key_name", ConfigConstant.MEMBER_DEFAULT_AVATAR));
return appConfig.getKeyValue();
}
}

View File

@@ -18,6 +18,7 @@ package xyz.playedu.common.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -108,7 +109,7 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
private void updateParentChain(String newChildrenPC, String oldChildrenPC) {
List<Department> children =
list(query().getWrapper().like("parent_chain", oldChildrenPC + "%"));
if (children.size() == 0) {
if (children.isEmpty()) {
return;
}
@@ -125,7 +126,7 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
.getParentChain()
.replaceFirst(
oldChildrenPC + ",",
newChildrenPC.length() == 0
newChildrenPC.isEmpty()
? newChildrenPC
: newChildrenPC + ',');
}
@@ -133,7 +134,7 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
// parentId计算
int parentId = 0;
if (pc != null && pc.length() > 0) {
if (pc != null && !pc.isEmpty()) {
String[] parentIds = pc.split(",");
parentId = Integer.parseInt(parentIds[parentIds.length - 1]);
}
@@ -153,7 +154,7 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
throw new NotFoundException("父级部门不存在");
}
String pc = parentDepartment.getParentChain();
parentChain = pc == null || pc.length() == 0 ? parentId + "" : pc + "," + parentId;
parentChain = pc == null || pc.isEmpty() ? parentId + "" : pc + "," + parentId;
}
return parentChain;
}
@@ -161,14 +162,14 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
@Override
public String childrenParentChain(Department department) {
String prefix = department.getId() + "";
if (department.getParentChain() != null && department.getParentChain().length() > 0) {
if (department.getParentChain() != null && !department.getParentChain().isEmpty()) {
prefix = department.getParentChain() + "," + prefix;
}
return prefix;
}
@Override
public void create(String name, Integer parentId, Integer sort) throws NotFoundException {
public Integer create(String name, Integer parentId, Integer sort) throws NotFoundException {
String parentChain = "";
if (parentId != 0) {
parentChain = compParentChain(parentId);
@@ -183,6 +184,8 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
department.setUpdatedAt(new Date());
save(department);
return department.getId();
}
@Override
@@ -258,9 +261,31 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
@Override
public List<Department> chunk(List<Integer> ids) {
if (ids == null || ids.size() == 0) {
if (ids == null || ids.isEmpty()) {
return new ArrayList<>();
}
return list(query().getWrapper().in("id", ids));
}
@Override
@SneakyThrows
public Integer createWithChainList(List<String> ou) {
if (ou == null || ou.isEmpty()) {
return 0;
}
Department department = null;
for (int i = 0; i < ou.size(); i++) {
String name = ou.get(i);
Integer parentId = department == null ? 0 : department.getId();
department = getOne(query().getWrapper().eq("name", name).eq("parent_id", parentId));
if (department == null) {
Integer depId = create(name, parentId, i);
// refresh
department = new Department();
department.setId(depId);
}
}
return department.getId();
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2023 杭州白书科技有限公司
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.playedu.common.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import xyz.playedu.common.domain.LdapUser;
import xyz.playedu.common.mapper.LdapUserMapper;
import xyz.playedu.common.service.LdapUserService;
import xyz.playedu.common.util.StringUtil;
import xyz.playedu.common.util.ldap.LdapTransformUser;
import java.util.Date;
/**
* @author tengyongzhi
* @description 针对表【ldap_user】的数据库操作Service实现
* @createDate 2023-08-31 11:59:27
*/
@Service
public class LdapUserServiceImpl extends ServiceImpl<LdapUserMapper, LdapUser>
implements LdapUserService {
@Override
public LdapUser findByUUID(String id) {
return getOne(query().getWrapper().eq("uuid", id));
}
@Override
public LdapUser store(LdapTransformUser ldapTransformUser) {
LdapUser user = new LdapUser();
user.setUuid(ldapTransformUser.getId());
user.setCn(ldapTransformUser.getCn());
user.setDn(ldapTransformUser.getDn());
user.setUid(ldapTransformUser.getUid());
// ou
user.setOu(String.join(",", ldapTransformUser.getOu()));
// 邮箱可能不存在
if (StringUtil.isNotEmpty(ldapTransformUser.getEmail())) {
user.setEmail(ldapTransformUser.getEmail());
}
user.setCreatedAt(new Date());
user.setUpdatedAt(new Date());
save(user);
return user;
}
@Override
public void updateUserId(Integer id, Integer userId) {
LdapUser user = new LdapUser();
user.setId(id);
user.setUserId(userId);
updateById(user);
}
@Override
public void updateCN(Integer id, String cn) {
LdapUser user = new LdapUser();
user.setId(id);
user.setCn(cn == null ? "" : cn);
updateById(user);
}
@Override
public void updateOU(Integer id, String newOU) {
LdapUser user = new LdapUser();
user.setId(id);
user.setOu(newOU == null ? "" : newOU);
updateById(user);
}
@Override
public void updateEmail(Integer id, String email) {
LdapUser user = new LdapUser();
user.setId(id);
user.setEmail(email == null ? "" : email);
updateById(user);
}
@Override
public void updateUid(Integer id, String uid) {
LdapUser user = new LdapUser();
user.setId(id);
user.setUid(uid);
updateById(user);
}
}

View File

@@ -117,7 +117,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
user.setCreatedAt(new Date());
user.setUpdatedAt(new Date());
if (idCard != null && idCard.length() > 0) {
if (idCard != null && !idCard.isEmpty()) {
user.setVerifyAt(new Date());
user.setIsVerify(1);
}
@@ -144,14 +144,14 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
newUser.setAvatar(avatar);
newUser.setIdCard(idCard);
if (password != null && password.length() > 0) {
if (password != null && !password.isEmpty()) {
newUser.setPassword(HelperUtil.MD5(password + user.getSalt()));
}
if (newUser.getName() != null
&& newUser.getName().length() > 0
&& !newUser.getName().isEmpty()
&& newUser.getIdCard() != null
&& newUser.getIdCard().length() > 0) {
&& !newUser.getIdCard().isEmpty()) {
if (user.getVerifyAt() == null) {
newUser.setIsVerify(1);
newUser.setVerifyAt(new Date());
@@ -204,7 +204,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
public List<User> chunks(List<Integer> ids, List<String> fields) {
if (ids == null || ids.size() == 0) {
if (ids == null || ids.isEmpty()) {
return new ArrayList<>();
}
return list(query().getWrapper().in("id", ids).select(fields));
@@ -212,7 +212,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
public List<User> chunks(List<Integer> ids) {
if (ids == null || ids.size() == 0) {
if (ids == null || ids.isEmpty()) {
return new ArrayList<>();
}
return list(query().getWrapper().in("id", ids));
@@ -250,7 +250,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
public Map<Integer, List<Integer>> getDepIdsGroup(List<Integer> userIds) {
if (userIds == null || userIds.size() == 0) {
if (userIds == null || userIds.isEmpty()) {
return null;
}
Map<Integer, List<UserDepartment>> data =
@@ -273,4 +273,25 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
user.setAvatar(avatar);
updateById(user);
}
@Override
public void updateName(Integer id, String cn) {
User user = new User();
user.setId(id);
user.setName(cn);
updateById(user);
}
@Override
public void updateDepId(Integer id, Integer[] depIds) {
userDepartmentService.resetStoreDepIds(id, depIds);
}
@Override
public void updateEmail(Integer id, String email) {
User user = new User();
user.setId(id);
user.setEmail(email);
updateById(user);
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2023 杭州白书科技有限公司
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.playedu.common.util.ldap;
import lombok.Data;
import java.util.List;
@Data
public class LdapTransformUser {
private String id;
private String dn;
private String cn;
private List<String> ou;
private String email;
private String uid;
}

View File

@@ -0,0 +1,229 @@
/*
* Copyright (C) 2023 杭州白书科技有限公司
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.playedu.common.util.ldap;
import lombok.extern.slf4j.Slf4j;
import xyz.playedu.common.exception.ServiceException;
import xyz.playedu.common.util.StringUtil;
import java.util.*;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
@Slf4j
public class LdapUtil {
private static final String USER_OBJECT_CLASS =
"(|(objectClass=person)(objectClass=posixAccount)(objectClass=inetOrgPerson)(objectClass=organizationalPerson))";
private static final String[] USER_RETURN_ATTRS =
new String[] {
"uid", // 用户的唯一识别符号,全局唯一,可以看做用户表的手机号,此字段可用于配合密码直接登录
"cn", // CommonName -> 可以认作为人的名字比如张三。在LDAP中此字段是可以重复的,但是同一ou下不可重复
"mail", // 邮箱,此值不一定存在,全局唯一,可配合密码直接登录
"email", // 邮箱,同上
"entryUUID",
};
private static final String[] OU_RETURN_ATTRS = new String[] {"ou"};
public static LdapContext initContext(String url, String adminUser, String adminPass)
throws NamingException {
Hashtable<String, String> context = new Hashtable<>();
context.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
context.put(Context.SECURITY_AUTHENTICATION, "simple");
// 服务地址
context.put(Context.PROVIDER_URL, url);
// 管理员账户和密码
context.put(Context.SECURITY_PRINCIPAL, adminUser);
context.put(Context.SECURITY_CREDENTIALS, adminPass);
return new InitialLdapContext(context, null);
}
public static List<HashMap<String, String>> users(LdapContext ldapContext, String baseDN)
throws NamingException {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setReturningAttributes(USER_RETURN_ATTRS);
controls.setReturningObjFlag(true);
NamingEnumeration<SearchResult> result = null;
try {
result = ldapContext.search(baseDN, USER_OBJECT_CLASS, controls);
} catch (NamingException e) {
log.error("LDAP用户查询失败", e);
} finally {
closeContext(ldapContext);
}
if (result == null || !result.hasMoreElements()) {
log.info("LDAP服务中没有用户");
return null;
}
List<HashMap<String, String>> users = new ArrayList<>();
while (result.hasMoreElements()) {
SearchResult item = result.nextElement();
if (item == null) {
continue;
}
Attributes attributes = item.getAttributes();
log.info("name={},attributes={}", item.getName(), attributes);
}
return users;
}
public static List<String> departments(LdapContext ldapContext, String baseDN)
throws NamingException {
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setReturningAttributes(OU_RETURN_ATTRS);
controls.setReturningObjFlag(true);
String filter = "(objectClass=organizationalUnit)";
NamingEnumeration<SearchResult> result = null;
try {
result = ldapContext.search(baseDN, filter, controls);
} catch (NamingException e) {
log.error("LDAP部门查询失败", e);
} finally {
closeContext(ldapContext);
}
if (result == null || !result.hasMoreElements()) {
log.info("LDAP部门为空");
return null;
}
List<String> units = new ArrayList<>();
while (result.hasMoreElements()) {
SearchResult item = result.nextElement();
if (item == null) {
continue;
}
units.add(item.getName());
}
return units;
}
public static LdapTransformUser loginByMailOrUid(
String url,
String adminUser,
String adminPass,
String baseDN,
String mail,
String uid,
String password)
throws ServiceException, NamingException {
if (StringUtil.isEmpty(mail) && StringUtil.isEmpty(uid)) {
throw new ServiceException("mail和Uid不能同时为空");
}
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setReturningAttributes(USER_RETURN_ATTRS);
controls.setReturningObjFlag(true);
controls.setCountLimit(1);
String userFilter = "";
if (StringUtil.isNotEmpty(mail)) {
userFilter = String.format("(|(mail=%s)(email=%s))", mail, mail);
} else if (StringUtil.isNotEmpty(uid)) {
userFilter = String.format("(uid=%s)", uid);
}
String filter = String.format("(&%s%s)", userFilter, USER_OBJECT_CLASS);
LdapContext ldapContext = initContext(url, adminUser, adminPass);
NamingEnumeration<SearchResult> result = null;
try {
result = ldapContext.search(baseDN, filter, controls);
} catch (NamingException e) {
log.error("通过mail或uid登录失败", e);
} finally {
closeContext(ldapContext);
}
if (result == null || !result.hasMoreElements()) {
log.info("用户不存在");
return null;
}
// 根据mail或uid查询出来的用户
SearchResult item = result.nextElement();
Attributes attributes = item.getAttributes();
String email =
attributes.get("mail") == null ? null : (String) attributes.get("mail").get();
if (email == null) {
email = attributes.get("email") == null ? null : (String) attributes.get("email").get();
}
LdapTransformUser ldapUser = new LdapTransformUser();
ldapUser.setDn(item.getName());
ldapUser.setId((String) attributes.get("entryUUID").get());
ldapUser.setCn((String) attributes.get("cn").get());
ldapUser.setUid((String) attributes.get("uid").get());
ldapUser.setEmail(email);
// 使用用户dn+提交的密码去登录ldap系统
// 登录成功则意味着密码正确
// 登录失败则意味着密码错误
try {
ldapContext = initContext(url, ldapUser.getDn() + "," + baseDN, password);
log.info("LDAP登录成功");
} catch (Exception e) {
// 无法登录->密码错误
log.info("LDAP用户提交的密码错误");
return null;
} finally {
ldapContext.close();
}
// ou计算
String[] rdnList = ldapUser.getDn().split(",");
List<String> ou = new ArrayList<>();
for (String s : rdnList) {
if (StringUtil.startsWith(s, "ou=")) {
ou.add(s.replace("ou=", ""));
}
}
Collections.reverse(ou);
ldapUser.setOu(ou);
return ldapUser;
}
public static void closeContext(LdapContext ldapCtx) {
if (ldapCtx == null) {
return;
}
try {
ldapCtx.close();
} catch (NamingException e) {
log.error("Failed to close ldap context", e);
}
}
}

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.playedu.common.mapper.LdapUserMapper">
<resultMap id="BaseResultMap" type="xyz.playedu.common.domain.LdapUser">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="uuid" column="uuid" jdbcType="VARCHAR"/>
<result property="userId" column="user_id" jdbcType="INTEGER"/>
<result property="cn" column="cn" jdbcType="VARCHAR"/>
<result property="dn" column="dn" jdbcType="VARCHAR"/>
<result property="ou" column="ou" jdbcType="VARCHAR"/>
<result property="uid" column="uid" jdbcType="VARCHAR"/>
<result property="email" column="email" jdbcType="VARCHAR"/>
<result property="createdAt" column="created_at" jdbcType="TIMESTAMP"/>
<result property="updatedAt" column="updated_at" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,uuid,user_id,
cn,dn,ou,
uid,email,created_at,
updated_at
</sql>
</mapper>