fix: LDAP支持邮箱登录
This commit is contained in:
parent
5d2844c4d3
commit
ffd4ae427d
|
@ -7,12 +7,12 @@ import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.controller.ResultHolder;
|
import io.metersphere.controller.ResultHolder;
|
||||||
import io.metersphere.controller.request.LoginRequest;
|
import io.metersphere.controller.request.LoginRequest;
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.ldap.domain.Person;
|
|
||||||
import io.metersphere.ldap.service.LdapService;
|
import io.metersphere.ldap.service.LdapService;
|
||||||
import io.metersphere.service.SystemParameterService;
|
import io.metersphere.service.SystemParameterService;
|
||||||
import io.metersphere.service.UserService;
|
import io.metersphere.service.UserService;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
import org.springframework.ldap.core.DirContextOperations;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
@ -36,29 +36,37 @@ public class LdapController {
|
||||||
MSException.throwException(Translator.get("ldap_authentication_not_enabled"));
|
MSException.throwException(Translator.get("ldap_authentication_not_enabled"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Person person = ldapService.authenticate(request);
|
DirContextOperations dirContext = ldapService.authenticate(request);
|
||||||
|
String email = ldapService.getMappingAttr("email", dirContext);
|
||||||
|
String userId = ldapService.getMappingAttr("username", dirContext);
|
||||||
|
|
||||||
SecurityUtils.getSubject().getSession().setAttribute("authenticate", UserSource.LDAP.name());
|
SecurityUtils.getSubject().getSession().setAttribute("authenticate", UserSource.LDAP.name());
|
||||||
|
SecurityUtils.getSubject().getSession().setAttribute("email", email);
|
||||||
|
|
||||||
String username = request.getUsername();
|
|
||||||
|
|
||||||
String email = person.getEmail();
|
|
||||||
|
|
||||||
if (StringUtils.isBlank(email)) {
|
if (StringUtils.isBlank(email)) {
|
||||||
MSException.throwException(Translator.get("login_fail_email_null"));
|
MSException.throwException(Translator.get("login_fail_email_null"));
|
||||||
}
|
}
|
||||||
|
|
||||||
User u = userService.selectUser(request.getUsername());
|
// userId 或 email 有一个相同即为存在本地用户
|
||||||
|
User u = userService.selectUser(userId, email);
|
||||||
if (u == null) {
|
if (u == null) {
|
||||||
|
|
||||||
|
// 新建用户 获取LDAP映射属性
|
||||||
|
String name = ldapService.getMappingAttr("name", dirContext);
|
||||||
|
|
||||||
User user = new User();
|
User user = new User();
|
||||||
user.setId(username);
|
user.setId(userId);
|
||||||
user.setName(username);
|
user.setName(name);
|
||||||
user.setEmail(email);
|
user.setEmail(email);
|
||||||
user.setSource(UserSource.LDAP.name());
|
user.setSource(UserSource.LDAP.name());
|
||||||
userService.addLdapUser(user);
|
userService.addLdapUser(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
return userService.login(request);
|
// 执行 ShiroDBRealm 中 LDAP 登录逻辑
|
||||||
|
LoginRequest loginRequest = new LoginRequest();
|
||||||
|
loginRequest.setUsername(userId);
|
||||||
|
return userService.login(loginRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/test/connect")
|
@PostMapping("/test/connect")
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
package io.metersphere.ldap.dao;
|
|
||||||
|
|
||||||
|
|
||||||
import io.metersphere.ldap.domain.Person;
|
|
||||||
|
|
||||||
public interface PersonRepo {
|
|
||||||
|
|
||||||
Person getDnForUser(String name);
|
|
||||||
}
|
|
|
@ -1,177 +0,0 @@
|
||||||
package io.metersphere.ldap.dao;
|
|
||||||
|
|
||||||
|
|
||||||
import io.metersphere.commons.constants.ParamConstants;
|
|
||||||
import io.metersphere.commons.exception.MSException;
|
|
||||||
import io.metersphere.commons.utils.EncryptUtils;
|
|
||||||
import io.metersphere.i18n.Translator;
|
|
||||||
import io.metersphere.ldap.domain.Person;
|
|
||||||
import io.metersphere.service.SystemParameterService;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.shiro.realm.ldap.LdapUtils;
|
|
||||||
import org.springframework.ldap.AuthenticationException;
|
|
||||||
import org.springframework.ldap.InvalidNameException;
|
|
||||||
import org.springframework.ldap.InvalidSearchFilterException;
|
|
||||||
import org.springframework.ldap.NameNotFoundException;
|
|
||||||
import org.springframework.ldap.core.*;
|
|
||||||
import org.springframework.ldap.core.support.AbstractContextMapper;
|
|
||||||
import org.springframework.ldap.core.support.DefaultDirObjectFactory;
|
|
||||||
import org.springframework.ldap.core.support.LdapContextSource;
|
|
||||||
import org.springframework.ldap.query.SearchScope;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.naming.directory.DirContext;
|
|
||||||
import javax.naming.ldap.LdapContext;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.springframework.ldap.query.LdapQueryBuilder.query;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class PersonRepoImpl implements PersonRepo {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private SystemParameterService service;
|
|
||||||
|
|
||||||
public boolean authenticate(String dn, String credentials) {
|
|
||||||
LdapTemplate ldapTemplate = getConnection();
|
|
||||||
return authenticate(dn, credentials, ldapTemplate);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean authenticate(String dn, String credentials, LdapTemplate ldapTemplate) throws AuthenticationException {
|
|
||||||
DirContext ctx = null;
|
|
||||||
try {
|
|
||||||
ctx = ldapTemplate.getContextSource().getContext(dn, credentials);
|
|
||||||
return true;
|
|
||||||
} finally {
|
|
||||||
// It is imperative that the created DirContext instance is always closed
|
|
||||||
LdapUtils.closeContext((LdapContext) ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Person getDnForUser(String username) {
|
|
||||||
LdapTemplate ldapTemplate = getConnection();
|
|
||||||
|
|
||||||
String filter = getUserFilter();
|
|
||||||
String[] arr = getUserOu();
|
|
||||||
|
|
||||||
List<Person> result = null;
|
|
||||||
for (String ou : arr) {
|
|
||||||
try {
|
|
||||||
result = ldapTemplate.search(query().base(ou.trim()).filter(filter, username), getContextMapper());
|
|
||||||
if (result.size() == 1) {
|
|
||||||
return result.get(0);
|
|
||||||
}
|
|
||||||
} catch (NameNotFoundException e) {
|
|
||||||
MSException.throwException(Translator.get("login_fail_ou_error"));
|
|
||||||
} catch (InvalidNameException e) {
|
|
||||||
MSException.throwException(Translator.get("login_fail_ou_error"));
|
|
||||||
} catch (InvalidSearchFilterException e) {
|
|
||||||
MSException.throwException(Translator.get("login_fail_filter_error"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.size() != 1) {
|
|
||||||
MSException.throwException(Translator.get("user_not_found_or_not_unique"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getUserFilter() {
|
|
||||||
String filter = service.getValue(ParamConstants.LDAP.FILTER.getValue());
|
|
||||||
|
|
||||||
if (StringUtils.isBlank(filter)) {
|
|
||||||
MSException.throwException(Translator.get("ldap_user_filter_is_null"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String[] getUserOu() {
|
|
||||||
String ou = service.getValue(ParamConstants.LDAP.OU.getValue());
|
|
||||||
|
|
||||||
if (StringUtils.isBlank(ou)) {
|
|
||||||
MSException.throwException(Translator.get("ldap_ou_is_null"));
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] arr = ou.split("\\|");
|
|
||||||
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ContextMapper getContextMapper() {
|
|
||||||
return new PersonContextMapper();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class PersonContextMapper extends AbstractContextMapper<Person> {
|
|
||||||
@Override
|
|
||||||
public Person doMapFromContext(DirContextOperations context) {
|
|
||||||
Person person = new Person();
|
|
||||||
person.setDn(context.getNameInNamespace());
|
|
||||||
person.setUid(context.getStringAttribute("uid"));
|
|
||||||
person.setCommonName(context.getStringAttribute("cn"));
|
|
||||||
person.setSurName(context.getStringAttribute("sn"));
|
|
||||||
person.setUsername(context.getStringAttribute("sAMAccountName"));
|
|
||||||
person.setEmail(context.getStringAttribute("mail"));
|
|
||||||
return person;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LdapTemplate getConnection() {
|
|
||||||
|
|
||||||
String url = service.getValue(ParamConstants.LDAP.URL.getValue());
|
|
||||||
String dn = service.getValue(ParamConstants.LDAP.DN.getValue());
|
|
||||||
String password = service.getValue(ParamConstants.LDAP.PASSWORD.getValue());
|
|
||||||
|
|
||||||
preConnect(url, dn, password);
|
|
||||||
|
|
||||||
String credentials = EncryptUtils.aesDecrypt(password).toString();
|
|
||||||
|
|
||||||
LdapContextSource sourceLdapCtx = new LdapContextSource();
|
|
||||||
sourceLdapCtx.setUrl(url);
|
|
||||||
sourceLdapCtx.setUserDn(dn);
|
|
||||||
sourceLdapCtx.setPassword(credentials);
|
|
||||||
sourceLdapCtx.setDirObjectFactory(DefaultDirObjectFactory.class);
|
|
||||||
sourceLdapCtx.afterPropertiesSet();
|
|
||||||
LdapTemplate ldapTemplate = new LdapTemplate(sourceLdapCtx);
|
|
||||||
ldapTemplate.setIgnorePartialResultException(true);
|
|
||||||
Map<String, Object> baseEnv = new Hashtable<>();
|
|
||||||
baseEnv.put("com.sun.jndi.ldap.connect.timeout", "3000");
|
|
||||||
baseEnv.put("com.sun.jndi.ldap.read.timeout", "3000");
|
|
||||||
sourceLdapCtx.setBaseEnvironmentProperties(baseEnv);
|
|
||||||
ldapTemplate.setDefaultSearchScope(SearchScope.SUBTREE.getId());
|
|
||||||
|
|
||||||
// ldapTemplate 是否可用
|
|
||||||
try {
|
|
||||||
authenticate(dn, credentials, ldapTemplate);
|
|
||||||
} catch (AuthenticationException e) {
|
|
||||||
MSException.throwException(Translator.get("ldap_connect_fail_user"));
|
|
||||||
} catch (Exception e) {
|
|
||||||
MSException.throwException(Translator.get("ldap_connect_fail"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ldapTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void preConnect(String url, String dn, String password) {
|
|
||||||
|
|
||||||
if (StringUtils.isBlank(url)) {
|
|
||||||
MSException.throwException(Translator.get("ldap_url_is_null"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isBlank(dn)) {
|
|
||||||
MSException.throwException(Translator.get("ldap_dn_is_null"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isBlank(password)) {
|
|
||||||
MSException.throwException(Translator.get("ldap_password_is_null"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,39 +1,221 @@
|
||||||
package io.metersphere.ldap.service;
|
package io.metersphere.ldap.service;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import io.metersphere.commons.constants.ParamConstants;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
|
import io.metersphere.commons.utils.EncryptUtils;
|
||||||
import io.metersphere.controller.request.LoginRequest;
|
import io.metersphere.controller.request.LoginRequest;
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.ldap.dao.PersonRepoImpl;
|
import io.metersphere.service.SystemParameterService;
|
||||||
import io.metersphere.ldap.domain.Person;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.shiro.realm.ldap.LdapUtils;
|
||||||
import org.springframework.ldap.AuthenticationException;
|
import org.springframework.ldap.AuthenticationException;
|
||||||
|
import org.springframework.ldap.InvalidNameException;
|
||||||
|
import org.springframework.ldap.InvalidSearchFilterException;
|
||||||
|
import org.springframework.ldap.NameNotFoundException;
|
||||||
|
import org.springframework.ldap.core.DirContextOperations;
|
||||||
|
import org.springframework.ldap.core.LdapTemplate;
|
||||||
|
import org.springframework.ldap.core.support.AbstractContextMapper;
|
||||||
|
import org.springframework.ldap.core.support.DefaultDirObjectFactory;
|
||||||
|
import org.springframework.ldap.core.support.LdapContextSource;
|
||||||
|
import org.springframework.ldap.query.SearchScope;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.naming.directory.DirContext;
|
||||||
|
import javax.naming.ldap.LdapContext;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.springframework.ldap.query.LdapQueryBuilder.query;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class LdapService {
|
public class LdapService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private PersonRepoImpl personRepo;
|
private SystemParameterService service;
|
||||||
|
|
||||||
|
public DirContextOperations authenticate(LoginRequest request) {
|
||||||
public Person authenticate(LoginRequest request) {
|
|
||||||
String username = request.getUsername();
|
String username = request.getUsername();
|
||||||
String credentials = request.getPassword();
|
String credentials = request.getPassword();
|
||||||
Person person = null;
|
DirContextOperations dirContextOperations = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
person = personRepo.getDnForUser(username);
|
// 获取LDAP用户相关信息
|
||||||
personRepo.authenticate(person.getDn(), credentials);
|
dirContextOperations = getContextMapper(username);
|
||||||
|
// 执行登录认证
|
||||||
|
authenticate(String.valueOf(dirContextOperations.getDn()), credentials);
|
||||||
} catch (AuthenticationException e) {
|
} catch (AuthenticationException e) {
|
||||||
MSException.throwException(Translator.get("authentication_failed"));
|
MSException.throwException(Translator.get("authentication_failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return person;
|
// 检查属性是否存在
|
||||||
|
getMappingAttr("name", dirContextOperations);
|
||||||
|
getMappingAttr("email", dirContextOperations);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return dirContextOperations;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testConnect() {
|
public void testConnect() {
|
||||||
personRepo.getConnection();
|
getConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean authenticate(String dn, String credentials) {
|
||||||
|
LdapTemplate ldapTemplate = getConnection();
|
||||||
|
return authenticate(dn, credentials, ldapTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean authenticate(String dn, String credentials, LdapTemplate ldapTemplate) throws AuthenticationException {
|
||||||
|
DirContext ctx = null;
|
||||||
|
try {
|
||||||
|
ctx = ldapTemplate.getContextSource().getContext(dn, credentials);
|
||||||
|
return true;
|
||||||
|
} finally {
|
||||||
|
// It is imperative that the created DirContext instance is always closed
|
||||||
|
LdapUtils.closeContext((LdapContext) ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DirContextOperations getContextMapper(String username) {
|
||||||
|
LdapTemplate ldapTemplate = getConnection();
|
||||||
|
|
||||||
|
String filter = getUserFilter();
|
||||||
|
String[] arr = getUserOu();
|
||||||
|
|
||||||
|
List<DirContextOperations> result = null;
|
||||||
|
// 多OU
|
||||||
|
for (String ou : arr) {
|
||||||
|
try {
|
||||||
|
result = ldapTemplate.search(query().base(ou.trim()).filter(filter, username), new MsContextMapper());
|
||||||
|
if (result.size() == 1) {
|
||||||
|
return result.get(0);
|
||||||
|
}
|
||||||
|
} catch (NameNotFoundException e) {
|
||||||
|
MSException.throwException(Translator.get("login_fail_ou_error"));
|
||||||
|
} catch (InvalidNameException e) {
|
||||||
|
MSException.throwException(Translator.get("login_fail_ou_error"));
|
||||||
|
} catch (InvalidSearchFilterException e) {
|
||||||
|
MSException.throwException(Translator.get("login_fail_filter_error"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.size() != 1) {
|
||||||
|
MSException.throwException(Translator.get("user_not_found_or_not_unique"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getUserFilter() {
|
||||||
|
String filter = service.getValue(ParamConstants.LDAP.FILTER.getValue());
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(filter)) {
|
||||||
|
MSException.throwException(Translator.get("ldap_user_filter_is_null"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] getUserOu() {
|
||||||
|
String ou = service.getValue(ParamConstants.LDAP.OU.getValue());
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(ou)) {
|
||||||
|
MSException.throwException(Translator.get("ldap_ou_is_null"));
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] arr = ou.split("\\|");
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MsContextMapper extends AbstractContextMapper<DirContextOperations> {
|
||||||
|
@Override
|
||||||
|
public DirContextOperations doMapFromContext(DirContextOperations context) {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LdapTemplate getConnection() {
|
||||||
|
|
||||||
|
String url = service.getValue(ParamConstants.LDAP.URL.getValue());
|
||||||
|
String dn = service.getValue(ParamConstants.LDAP.DN.getValue());
|
||||||
|
String password = service.getValue(ParamConstants.LDAP.PASSWORD.getValue());
|
||||||
|
|
||||||
|
preConnect(url, dn, password);
|
||||||
|
|
||||||
|
String credentials = EncryptUtils.aesDecrypt(password).toString();
|
||||||
|
|
||||||
|
LdapContextSource sourceLdapCtx = new LdapContextSource();
|
||||||
|
sourceLdapCtx.setUrl(url);
|
||||||
|
sourceLdapCtx.setUserDn(dn);
|
||||||
|
sourceLdapCtx.setPassword(credentials);
|
||||||
|
sourceLdapCtx.setDirObjectFactory(DefaultDirObjectFactory.class);
|
||||||
|
sourceLdapCtx.afterPropertiesSet();
|
||||||
|
LdapTemplate ldapTemplate = new LdapTemplate(sourceLdapCtx);
|
||||||
|
ldapTemplate.setIgnorePartialResultException(true);
|
||||||
|
Map<String, Object> baseEnv = new Hashtable<>();
|
||||||
|
baseEnv.put("com.sun.jndi.ldap.connect.timeout", "3000");
|
||||||
|
baseEnv.put("com.sun.jndi.ldap.read.timeout", "3000");
|
||||||
|
sourceLdapCtx.setBaseEnvironmentProperties(baseEnv);
|
||||||
|
ldapTemplate.setDefaultSearchScope(SearchScope.SUBTREE.getId());
|
||||||
|
|
||||||
|
// ldapTemplate 是否可用
|
||||||
|
try {
|
||||||
|
authenticate(dn, credentials, ldapTemplate);
|
||||||
|
} catch (AuthenticationException e) {
|
||||||
|
MSException.throwException(Translator.get("ldap_connect_fail_user"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
MSException.throwException(Translator.get("ldap_connect_fail"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ldapTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void preConnect(String url, String dn, String password) {
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(url)) {
|
||||||
|
MSException.throwException(Translator.get("ldap_url_is_null"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(dn)) {
|
||||||
|
MSException.throwException(Translator.get("ldap_dn_is_null"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(password)) {
|
||||||
|
MSException.throwException(Translator.get("ldap_password_is_null"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getLdapMapping() {
|
||||||
|
String mapping = service.getValue(ParamConstants.LDAP.MAPPING.getValue());
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(mapping)) {
|
||||||
|
MSException.throwException(Translator.get("ldap_user_mapping_is_null"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMappingAttr(String attr, DirContextOperations dirContext) {
|
||||||
|
// 检查LDAP映射属性
|
||||||
|
String mapping = getLdapMapping();
|
||||||
|
JSONObject jsonObject = JSONObject.parseObject(mapping);
|
||||||
|
|
||||||
|
String mapAttr = jsonObject.getString(attr);
|
||||||
|
if (StringUtils.isBlank(mapAttr)) {
|
||||||
|
MSException.throwException(Translator.get("check_ldap_mapping") + " " + attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = dirContext.getStringAttribute(mapAttr);
|
||||||
|
if (StringUtils.isBlank(result)) {
|
||||||
|
MSException.throwException(Translator.get("ldap_mapping_value_null") + " " + mapAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,15 +112,19 @@ public class ShiroDBRealm extends AuthorizingRealm {
|
||||||
|
|
||||||
|
|
||||||
private AuthenticationInfo loginLdapMode(String userId, String password) {
|
private AuthenticationInfo loginLdapMode(String userId, String password) {
|
||||||
//
|
// userId 或 email 有一个相同就返回User
|
||||||
|
String email = (String) SecurityUtils.getSubject().getSession().getAttribute("email");
|
||||||
UserDTO user = userService.getLoginUser(userId, Arrays.asList(UserSource.LDAP.name(), UserSource.LOCAL.name()));
|
UserDTO user = userService.getLoginUser(userId, Arrays.asList(UserSource.LDAP.name(), UserSource.LOCAL.name()));
|
||||||
String msg;
|
String msg;
|
||||||
|
if (user == null) {
|
||||||
|
user = userService.getLoginUserByEmail(email, Arrays.asList(UserSource.LDAP.name(), UserSource.LOCAL.name()));
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
msg = "The user does not exist: " + userId;
|
msg = "The user does not exist: " + userId;
|
||||||
logger.warn(msg);
|
logger.warn(msg);
|
||||||
throw new UnknownAccountException(Translator.get("user_not_exist") + userId);
|
throw new UnknownAccountException(Translator.get("user_not_exist") + userId);
|
||||||
}
|
}
|
||||||
userId = user.getId();
|
userId = user.getId();
|
||||||
|
}
|
||||||
|
|
||||||
SessionUser sessionUser = SessionUser.fromUser(user);
|
SessionUser sessionUser = SessionUser.fromUser(user);
|
||||||
SessionUtils.putUser(sessionUser);
|
SessionUtils.putUser(sessionUser);
|
||||||
|
@ -132,7 +136,7 @@ public class ShiroDBRealm extends AuthorizingRealm {
|
||||||
UserDTO user = userService.getLoginUser(userId, Collections.singletonList(UserSource.LOCAL.name()));
|
UserDTO user = userService.getLoginUser(userId, Collections.singletonList(UserSource.LOCAL.name()));
|
||||||
String msg;
|
String msg;
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
user = userService.getLoginUserByEmail(userId, UserSource.LOCAL.name());
|
user = userService.getLoginUserByEmail(userId, Collections.singletonList(UserSource.LOCAL.name()));
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
msg = "The user does not exist: " + userId;
|
msg = "The user does not exist: " + userId;
|
||||||
logger.warn(msg);
|
logger.warn(msg);
|
||||||
|
|
|
@ -78,8 +78,18 @@ public class UserService {
|
||||||
return getUserDTO(user.getId());
|
return getUserDTO(user.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public User selectUser(String id) {
|
public User selectUser(String userId, String email) {
|
||||||
return userMapper.selectByPrimaryKey(id);
|
User user = userMapper.selectByPrimaryKey(userId);
|
||||||
|
if (user == null) {
|
||||||
|
UserExample example = new UserExample();
|
||||||
|
example.createCriteria().andEmailEqualTo(email);
|
||||||
|
List<User> users = userMapper.selectByExample(example);
|
||||||
|
if (!CollectionUtils.isEmpty(users)) {
|
||||||
|
return users.get(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void insertUserRole(List<Map<String, Object>> roles, String userId) {
|
private void insertUserRole(List<Map<String, Object>> roles, String userId) {
|
||||||
|
@ -199,9 +209,9 @@ public class UserService {
|
||||||
return getUserDTO(users.get(0).getId());
|
return getUserDTO(users.get(0).getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserDTO getLoginUserByEmail(String email, String source) {
|
public UserDTO getLoginUserByEmail(String email, List<String> list) {
|
||||||
UserExample example = new UserExample();
|
UserExample example = new UserExample();
|
||||||
example.createCriteria().andEmailEqualTo(email).andSourceEqualTo(source);
|
example.createCriteria().andEmailEqualTo(email).andSourceIn(list);
|
||||||
List<User> users = userMapper.selectByExample(example);
|
List<User> users = userMapper.selectByExample(example);
|
||||||
if (users == null || users.size() <= 0) {
|
if (users == null || users.size() <= 0) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -126,6 +126,7 @@ ldap_password_is_null=LDAP password is empty
|
||||||
ldap_connect_fail=Connection LDAP failed
|
ldap_connect_fail=Connection LDAP failed
|
||||||
ldap_connect_fail_user=Connection LDAP failed, wrong DN or password bound
|
ldap_connect_fail_user=Connection LDAP failed, wrong DN or password bound
|
||||||
ldap_user_filter_is_null=LDAP user filter is empty
|
ldap_user_filter_is_null=LDAP user filter is empty
|
||||||
|
ldap_user_mapping_is_null=LDAP user mapping is empty
|
||||||
authentication_failed=User authentication failed,wrong user name or password
|
authentication_failed=User authentication failed,wrong user name or password
|
||||||
user_not_found_or_not_unique=User does not exist or is not unique
|
user_not_found_or_not_unique=User does not exist or is not unique
|
||||||
find_more_user=Multiple users found
|
find_more_user=Multiple users found
|
||||||
|
@ -133,3 +134,5 @@ ldap_authentication_not_enabled=LDAP authentication is not enabled
|
||||||
login_fail_email_null=Login failed, user mailbox is empty
|
login_fail_email_null=Login failed, user mailbox is empty
|
||||||
login_fail_ou_error=Login failed, please check the user OU
|
login_fail_ou_error=Login failed, please check the user OU
|
||||||
login_fail_filter_error=Login failed, please check the user filter
|
login_fail_filter_error=Login failed, please check the user filter
|
||||||
|
check_ldap_mapping=Check LDAP attribute mapping
|
||||||
|
ldap_mapping_value_null=LDAP user attribute mapping field is empty
|
|
@ -126,6 +126,7 @@ ldap_password_is_null=LDAP密码为空
|
||||||
ldap_connect_fail=连接LDAP失败
|
ldap_connect_fail=连接LDAP失败
|
||||||
ldap_connect_fail_user=连接LDAP失败,绑定的DN或密码错误
|
ldap_connect_fail_user=连接LDAP失败,绑定的DN或密码错误
|
||||||
ldap_user_filter_is_null=LDAP用户过滤器为空
|
ldap_user_filter_is_null=LDAP用户过滤器为空
|
||||||
|
ldap_user_mapping_is_null=LDAP用户属性映射为空
|
||||||
authentication_failed=用户认证失败,用户名或密码错误
|
authentication_failed=用户认证失败,用户名或密码错误
|
||||||
user_not_found_or_not_unique=用户不存在或者不唯一
|
user_not_found_or_not_unique=用户不存在或者不唯一
|
||||||
find_more_user=查找到多个用户
|
find_more_user=查找到多个用户
|
||||||
|
@ -133,5 +134,7 @@ ldap_authentication_not_enabled=LDAP认证未启用
|
||||||
login_fail_email_null=登录失败,用户邮箱为空
|
login_fail_email_null=登录失败,用户邮箱为空
|
||||||
login_fail_ou_error=登录失败,请检查用户OU
|
login_fail_ou_error=登录失败,请检查用户OU
|
||||||
login_fail_filter_error=登录失败,请检查用户过滤器
|
login_fail_filter_error=登录失败,请检查用户过滤器
|
||||||
|
check_ldap_mapping=检查LDAP属性映射
|
||||||
|
ldap_mapping_value_null=LDAP用户属性映射字段为空值
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,7 @@ ldap_password_is_null=LDAP密碼為空
|
||||||
ldap_connect_fail=連接LDAP失敗
|
ldap_connect_fail=連接LDAP失敗
|
||||||
ldap_connect_fail_user=連接LDAP失敗,綁定的DN或密碼錯誤
|
ldap_connect_fail_user=連接LDAP失敗,綁定的DN或密碼錯誤
|
||||||
ldap_user_filter_is_null=LDAP用戶過濾器為空
|
ldap_user_filter_is_null=LDAP用戶過濾器為空
|
||||||
|
ldap_user_mapping_is_null=LDAP用戶屬性映射為空
|
||||||
authentication_failed=用戶認證失敗,用戶名或密碼錯誤
|
authentication_failed=用戶認證失敗,用戶名或密碼錯誤
|
||||||
user_not_found_or_not_unique=用戶不存在或者不唯一
|
user_not_found_or_not_unique=用戶不存在或者不唯一
|
||||||
find_more_user=查找到多個用戶
|
find_more_user=查找到多個用戶
|
||||||
|
@ -133,3 +134,5 @@ ldap_authentication_not_enabled=LDAP認證未啟用
|
||||||
login_fail_email_null=登錄失敗,用戶郵箱為空
|
login_fail_email_null=登錄失敗,用戶郵箱為空
|
||||||
login_fail_ou_error=登錄失敗,請檢查用戶OU
|
login_fail_ou_error=登錄失敗,請檢查用戶OU
|
||||||
login_fail_filter_error=登錄失敗,請檢查用戶過濾器
|
login_fail_filter_error=登錄失敗,請檢查用戶過濾器
|
||||||
|
check_ldap_mapping=檢查LDAP屬性映射
|
||||||
|
ldap_mapping_value_null=LDAP用戶屬性映射預設為空值
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
<el-form-item :label="$t('ldap.filter')" prop="filter">
|
<el-form-item :label="$t('ldap.filter')" prop="filter">
|
||||||
<el-input v-model="form.filter" :placeholder="$t('ldap.input_filter_placeholder')"></el-input>
|
<el-input v-model="form.filter" :placeholder="$t('ldap.input_filter_placeholder')"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item :label="$t('ldap.mapping')" prop="mapping">-->
|
<el-form-item :label="$t('ldap.mapping')" prop="mapping">
|
||||||
<!-- <el-input v-model="form.mapping" :placeholder="$t('ldap.input_mapping')"></el-input>-->
|
<el-input v-model="form.mapping" :placeholder="$t('ldap.input_mapping')"></el-input>
|
||||||
<!-- </el-form-item>-->
|
</el-form-item>
|
||||||
<el-form-item :label="$t('ldap.open')" prop="open">
|
<el-form-item :label="$t('ldap.open')" prop="open">
|
||||||
<el-checkbox v-model="form.open"></el-checkbox>
|
<el-checkbox v-model="form.open"></el-checkbox>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
@ -82,7 +82,8 @@
|
||||||
dn: {required: true, message: this.$t('ldap.input_dn'), trigger: ['change', 'blur']},
|
dn: {required: true, message: this.$t('ldap.input_dn'), trigger: ['change', 'blur']},
|
||||||
password: {required: true, message: this.$t('ldap.input_password'), trigger: ['change', 'blur']},
|
password: {required: true, message: this.$t('ldap.input_password'), trigger: ['change', 'blur']},
|
||||||
ou: {required: true, message: this.$t('ldap.input_ou'), trigger: ['change', 'blur']},
|
ou: {required: true, message: this.$t('ldap.input_ou'), trigger: ['change', 'blur']},
|
||||||
filter: {required: true, message: this.$t('ldap.input_filter'), trigger: ['change', 'blur']}
|
filter: {required: true, message: this.$t('ldap.input_filter'), trigger: ['change', 'blur']},
|
||||||
|
mapping: {required: true, message: this.$t('ldap.input_mapping'), trigger: ['change', 'blur']}
|
||||||
},
|
},
|
||||||
loginFormRules: {
|
loginFormRules: {
|
||||||
username: {required: true, message: this.$t('ldap.input_username'), trigger: 'blur'},
|
username: {required: true, message: this.$t('ldap.input_username'), trigger: 'blur'},
|
||||||
|
@ -142,6 +143,11 @@
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.form.mapping) {
|
||||||
|
this.$warning(this.$t('ldap.mapping_cannot_be_empty'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
this.loginForm = {};
|
this.loginForm = {};
|
||||||
this.loginVisible = true;
|
this.loginVisible = true;
|
||||||
},
|
},
|
||||||
|
|
|
@ -677,6 +677,7 @@ export default {
|
||||||
ou_cannot_be_empty: 'LDAP OU cannot be empty',
|
ou_cannot_be_empty: 'LDAP OU cannot be empty',
|
||||||
filter_cannot_be_empty: 'LDAP user filter cannot be empty',
|
filter_cannot_be_empty: 'LDAP user filter cannot be empty',
|
||||||
password_cannot_be_empty: 'LDAP password cannot be empty',
|
password_cannot_be_empty: 'LDAP password cannot be empty',
|
||||||
|
mapping_cannot_be_empty: 'LDAP mapping cannot be empty',
|
||||||
},
|
},
|
||||||
schedule: {
|
schedule: {
|
||||||
not_set: "Not Set",
|
not_set: "Not Set",
|
||||||
|
|
|
@ -675,6 +675,7 @@ export default {
|
||||||
dn_cannot_be_empty: 'LDAP DN不能为空',
|
dn_cannot_be_empty: 'LDAP DN不能为空',
|
||||||
ou_cannot_be_empty: 'LDAP OU不能为空',
|
ou_cannot_be_empty: 'LDAP OU不能为空',
|
||||||
filter_cannot_be_empty: 'LDAP 用户过滤器不能为空',
|
filter_cannot_be_empty: 'LDAP 用户过滤器不能为空',
|
||||||
|
mapping_cannot_be_empty: 'LDAP 用户属性映射不能为空',
|
||||||
password_cannot_be_empty: 'LDAP 密码不能为空',
|
password_cannot_be_empty: 'LDAP 密码不能为空',
|
||||||
},
|
},
|
||||||
schedule: {
|
schedule: {
|
||||||
|
|
|
@ -675,6 +675,7 @@ export default {
|
||||||
ou_cannot_be_empty: 'LDAP OU不能為空',
|
ou_cannot_be_empty: 'LDAP OU不能為空',
|
||||||
filter_cannot_be_empty: 'LDAP 用戶過濾器不能為空',
|
filter_cannot_be_empty: 'LDAP 用戶過濾器不能為空',
|
||||||
password_cannot_be_empty: 'LDAP 密碼不能為空',
|
password_cannot_be_empty: 'LDAP 密碼不能為空',
|
||||||
|
mapping_cannot_be_empty: 'LDAP 用戶屬性映射不能為空',
|
||||||
},
|
},
|
||||||
schedule: {
|
schedule: {
|
||||||
not_set: "未設置",
|
not_set: "未設置",
|
||||||
|
|
Loading…
Reference in New Issue