Merge branch 'master' of https://github.com/metersphere/server
This commit is contained in:
commit
93b011a4ac
|
@ -54,14 +54,14 @@
|
|||
</if>
|
||||
</select>
|
||||
<select id="listByMethod" resultType="io.metersphere.track.dto.TestCaseDTO">
|
||||
SELECT id,name,status,project_id,type from api_test
|
||||
SELECT id,name,status,project_id,"api" as type from api_test
|
||||
<where>
|
||||
<if test="request.projectId!=null">
|
||||
and project_id=#{request.projectId}
|
||||
</if>
|
||||
</where>
|
||||
UNION ALL
|
||||
select id,name,status,project_id,type from load_test
|
||||
select id,name,status,project_id,"perform" as type from load_test
|
||||
<where>
|
||||
<if test="request.projectId!=null">
|
||||
and project_id= #{request.projectId}
|
||||
|
|
|
@ -66,7 +66,7 @@ public class LdapController {
|
|||
|
||||
@PostMapping("/test/connect")
|
||||
public void testConnect(@RequestBody LdapInfo ldapInfo) {
|
||||
ldapService.testConnect(ldapInfo);
|
||||
ldapService.testConnect();
|
||||
}
|
||||
|
||||
@PostMapping("/test/login")
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
package io.metersphere.ldap.dao;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import io.metersphere.ldap.domain.Person;
|
||||
|
||||
public interface PersonRepo {
|
||||
|
||||
List findByName(String name);
|
||||
|
||||
String getDnForUser(String name);
|
||||
Person getDnForUser(String name);
|
||||
}
|
||||
|
|
|
@ -4,23 +4,28 @@ 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.commons.utils.LogUtil;
|
||||
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.LdapQuery;
|
||||
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;
|
||||
|
||||
|
@ -35,58 +40,63 @@ public class PersonRepoImpl implements PersonRepo {
|
|||
return authenticate(dn, credentials, ldapTemplate);
|
||||
}
|
||||
|
||||
private boolean authenticate(String dn, String credentials, LdapTemplate ldapTemplate) {
|
||||
private boolean authenticate(String dn, String credentials, LdapTemplate ldapTemplate) throws AuthenticationException {
|
||||
DirContext ctx = null;
|
||||
try {
|
||||
ctx = ldapTemplate.getContextSource().getContext(dn, credentials);
|
||||
// ldapTemplate.authenticate(dn, credentials);
|
||||
// Take care here - if a base was specified on the ContextSource
|
||||
// that needs to be removed from the user DN for the lookup to succeed.
|
||||
// ctx.lookup(userDn);
|
||||
return true;
|
||||
} catch (AuthenticationException e) {
|
||||
LogUtil.error("ldap authenticate failed..." + e);
|
||||
System.out.println("Login failed: " + e);
|
||||
MSException.throwException(Translator.get("authentication_failed"));
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
// Context creation failed - authentication did not succeed
|
||||
LogUtil.error("ldap authenticate failed..." + e);
|
||||
System.out.println("Login failed: " + e);
|
||||
MSException.throwException(Translator.get("ldap_connect_fail"));
|
||||
return false;
|
||||
} finally {
|
||||
// It is imperative that the created DirContext instance is always closed
|
||||
LdapUtils.closeContext((LdapContext) ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Person> findByName(String name) {
|
||||
LdapTemplate ldapTemplate = getConnection();
|
||||
LdapQuery query = query().where("cn").is(name);
|
||||
return ldapTemplate.search(query, getContextMapper());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDnForUser(String uid) {
|
||||
public Person getDnForUser(String username) {
|
||||
LdapTemplate ldapTemplate = getConnection();
|
||||
List<String> result = ldapTemplate.search(
|
||||
query().where("cn").is(uid),
|
||||
new AbstractContextMapper() {
|
||||
@Override
|
||||
protected String doMapFromContext(DirContextOperations ctx) {
|
||||
return ctx.getNameInNamespace();
|
||||
}
|
||||
});
|
||||
|
||||
String filter = getUserFilter();
|
||||
String ou = getUserOu();
|
||||
|
||||
List<Person> result = null;
|
||||
try {
|
||||
result = ldapTemplate.search(query().base(ou).filter(filter, username), getContextMapper());
|
||||
} 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) {
|
||||
throw new RuntimeException(Translator.get("user_not_found_or_not_unique"));
|
||||
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"));
|
||||
}
|
||||
|
||||
return ou;
|
||||
}
|
||||
|
||||
protected ContextMapper getContextMapper() {
|
||||
return new PersonContextMapper();
|
||||
}
|
||||
|
@ -95,6 +105,8 @@ public class PersonRepoImpl implements PersonRepo {
|
|||
@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"));
|
||||
|
@ -107,10 +119,9 @@ public class PersonRepoImpl implements PersonRepo {
|
|||
|
||||
String url = service.getValue(ParamConstants.LDAP.URL.getValue());
|
||||
String dn = service.getValue(ParamConstants.LDAP.DN.getValue());
|
||||
String ou = service.getValue(ParamConstants.LDAP.OU.getValue());
|
||||
String password = service.getValue(ParamConstants.LDAP.PASSWORD.getValue());
|
||||
|
||||
preConnect(url, dn, ou, password);
|
||||
preConnect(url, dn, password);
|
||||
|
||||
String credentials = EncryptUtils.aesDecrypt(password).toString();
|
||||
|
||||
|
@ -118,19 +129,29 @@ public class PersonRepoImpl implements PersonRepo {
|
|||
sourceLdapCtx.setUrl(url);
|
||||
sourceLdapCtx.setUserDn(dn);
|
||||
sourceLdapCtx.setPassword(credentials);
|
||||
sourceLdapCtx.setBase(ou);
|
||||
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 是否可用
|
||||
authenticate(dn, credentials, 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 ou, String password) {
|
||||
private void preConnect(String url, String dn, String password) {
|
||||
|
||||
if (StringUtils.isBlank(url)) {
|
||||
MSException.throwException(Translator.get("ldap_url_is_null"));
|
||||
|
@ -140,10 +161,6 @@ public class PersonRepoImpl implements PersonRepo {
|
|||
MSException.throwException(Translator.get("ldap_dn_is_null"));
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(ou)) {
|
||||
MSException.throwException(Translator.get("ldap_ou_is_null"));
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(password)) {
|
||||
MSException.throwException(Translator.get("ldap_password_is_null"));
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ public class Person {
|
|||
|
||||
@Id
|
||||
private Name id;
|
||||
@DnAttribute(value="uid",index = 3)
|
||||
@DnAttribute(value="uid",index = 0)
|
||||
private String uid;
|
||||
@Attribute(name = "cn")
|
||||
private String commonName;
|
||||
|
@ -24,5 +24,6 @@ public class Person {
|
|||
private String username;
|
||||
@Attribute(name = "mail")
|
||||
private String email;
|
||||
private String dn;
|
||||
|
||||
}
|
|
@ -4,13 +4,11 @@ import io.metersphere.commons.exception.MSException;
|
|||
import io.metersphere.controller.request.LoginRequest;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.ldap.dao.PersonRepoImpl;
|
||||
import io.metersphere.ldap.domain.LdapInfo;
|
||||
import io.metersphere.ldap.domain.Person;
|
||||
import org.springframework.ldap.CommunicationException;
|
||||
import org.springframework.ldap.AuthenticationException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class LdapService {
|
||||
|
@ -20,32 +18,22 @@ public class LdapService {
|
|||
|
||||
|
||||
public Person authenticate(LoginRequest request) {
|
||||
String dn = null;
|
||||
String username = request.getUsername();
|
||||
String credentials = request.getPassword();
|
||||
Person person = null;
|
||||
|
||||
List<Person> personList = null;
|
||||
try {
|
||||
// select user by sAMAccountName
|
||||
personList = personRepo.findByName(username);
|
||||
|
||||
if (personList.size() == 1) {
|
||||
dn = personRepo.getDnForUser(username);
|
||||
} else if (personList.size() == 0) {
|
||||
MSException.throwException(Translator.get("user_not_exist") + username);
|
||||
} else {
|
||||
MSException.throwException(Translator.get("find_more_user"));
|
||||
}
|
||||
} catch (CommunicationException e) {
|
||||
MSException.throwException(Translator.get("ldap_connect_fail"));
|
||||
person = personRepo.getDnForUser(username);
|
||||
personRepo.authenticate(person.getDn(), credentials);
|
||||
} catch (AuthenticationException e) {
|
||||
MSException.throwException(Translator.get("authentication_failed"));
|
||||
}
|
||||
personRepo.authenticate(dn, credentials);
|
||||
|
||||
return personList.get(0);
|
||||
return person;
|
||||
}
|
||||
|
||||
public void testConnect(LdapInfo ldap) {
|
||||
personRepo.authenticate(ldap.getDn(), ldap.getPassword());
|
||||
public void testConnect() {
|
||||
personRepo.getConnection();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -120,9 +120,13 @@ ldap_url_is_null=LDAP address is empty
|
|||
ldap_dn_is_null=LDAP binding DN is empty
|
||||
ldap_ou_is_null=LDAP parameter OU is empty
|
||||
ldap_password_is_null=LDAP password is empty
|
||||
ldap_connect_fail=Connection failed
|
||||
ldap_connect_fail=Connection LDAP failed
|
||||
ldap_connect_fail_user=Connection LDAP failed, wrong DN or password bound
|
||||
ldap_user_filter_is_null=LDAP user filter is empty
|
||||
authentication_failed=User authentication failed,wrong user name or password
|
||||
user_not_found_or_not_unique=User does not exist or is not unique
|
||||
find_more_user=Multiple users found
|
||||
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_filter_error=Login failed, please check the user filter
|
|
@ -19,7 +19,7 @@ cannot_delete_current_user=无法删除当前登录用户
|
|||
connection_failed=连接失败
|
||||
user_already_exists=该用户已存在于当前成员列表中
|
||||
cannot_remove_current=无法移除当前登录用户
|
||||
login_fail=登陆失败
|
||||
login_fail=登录失败
|
||||
password_is_incorrect=密码不正确
|
||||
user_not_exist=用户不存在:
|
||||
user_has_been_disabled=用户已被禁用
|
||||
|
@ -120,11 +120,15 @@ ldap_url_is_null=LDAP地址为空
|
|||
ldap_dn_is_null=LDAP绑定DN为空
|
||||
ldap_ou_is_null=LDAP参数OU为空
|
||||
ldap_password_is_null=LDAP密码为空
|
||||
ldap_connect_fail=连接失败
|
||||
ldap_connect_fail=连接LDAP失败
|
||||
ldap_connect_fail_user=连接LDAP失败,绑定的DN或密码错误
|
||||
ldap_user_filter_is_null=LDAP用户过滤器为空
|
||||
authentication_failed=用户认证失败,用户名或密码错误
|
||||
user_not_found_or_not_unique=用户不存在或者不唯一
|
||||
find_more_user=查找到多个用户
|
||||
ldap_authentication_not_enabled=LDAP认证未启用
|
||||
login_fail_email_null=登录失败,用户邮箱为空
|
||||
login_fail_ou_error=登录失败,请检查用户OU
|
||||
login_fail_filter_error=登录失败,请检查用户过滤器
|
||||
|
||||
|
||||
|
|
|
@ -120,9 +120,13 @@ ldap_url_is_null=LDAP地址為空
|
|||
ldap_dn_is_null=LDAP綁定DN為空
|
||||
ldap_ou_is_null=LDAP參數OU為空
|
||||
ldap_password_is_null=LDAP密碼為空
|
||||
ldap_connect_fail=連接失敗
|
||||
ldap_connect_fail=連接LDAP失敗
|
||||
ldap_connect_fail_user=連接LDAP失敗,綁定的DN或密碼錯誤
|
||||
ldap_user_filter_is_null=LDAP用戶過濾器為空
|
||||
authentication_failed=用戶認證失敗,用戶名或密碼錯誤
|
||||
user_not_found_or_not_unique=用戶不存在或者不唯一
|
||||
find_more_user=查找到多個用戶
|
||||
ldap_authentication_not_enabled=LDAP認證未啟用
|
||||
login_fail_email_null=登錄失敗,用戶郵箱為空
|
||||
login_fail_ou_error=登錄失敗,請檢查用戶OU
|
||||
login_fail_filter_error=登錄失敗,請檢查用戶過濾器
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
dn: {required: true, message: this.$t('ldap.input_dn'), 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']},
|
||||
filter: {required: true, message: this.$t('ldap.input_filter'), trigger: ['change', 'blur']}
|
||||
},
|
||||
loginFormRules: {
|
||||
username: {required: true, message: this.$t('ldap.input_username'), trigger: 'blur'},
|
||||
|
@ -136,6 +137,11 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!this.form.filter) {
|
||||
this.$warning(this.$t('ldap.filter_cannot_be_empty'));
|
||||
return false;
|
||||
}
|
||||
|
||||
this.loginForm = {};
|
||||
this.loginVisible = true;
|
||||
},
|
||||
|
|
|
@ -612,7 +612,7 @@ export default {
|
|||
'input_username': 'please enter user name',
|
||||
'input_url_placeholder': 'Please enter the LDAP address (eg ldap://localhost:389)',
|
||||
'input_ou_placeholder': 'Enter user OU (use | to separate each OU)',
|
||||
'input_filter_placeholder': 'Input filter [Possible options are cn or uid or sAMAccountName=%(user)s]',
|
||||
'input_filter_placeholder': 'Input filter [Possible options are cn or uid or sAMAccountName={0}, eg: (uid={0})]',
|
||||
'test_connect': 'Test Connection',
|
||||
'test_login': 'Test Login',
|
||||
'edit': 'Edit',
|
||||
|
@ -620,6 +620,7 @@ export default {
|
|||
'url_cannot_be_empty': 'LDAP address cannot be empty',
|
||||
'dn_cannot_be_empty': 'LDAP DN cannot be empty',
|
||||
'ou_cannot_be_empty': 'LDAP OU cannot be empty',
|
||||
'filter_cannot_be_empty': 'LDAP user filter cannot be empty',
|
||||
'password_cannot_be_empty': 'LDAP password cannot be empty',
|
||||
},
|
||||
schedule: {
|
||||
|
|
|
@ -609,7 +609,7 @@ export default {
|
|||
'input_username': '请输入用户名',
|
||||
'input_url_placeholder': '请输入LDAP地址 (如 ldap://localhost:389)',
|
||||
'input_ou_placeholder': '输入用户OU (使用|分隔各OU)',
|
||||
'input_filter_placeholder': '输入过滤器 [可能的选项是cn或uid或sAMAccountName=%(user)s]',
|
||||
'input_filter_placeholder': '输入过滤器 [可能的选项是cn或uid或sAMAccountName={0}, 如:(uid={0})]',
|
||||
'test_connect': '测试连接',
|
||||
'test_login': '测试登录',
|
||||
'edit': '编辑',
|
||||
|
@ -617,6 +617,7 @@ export default {
|
|||
'url_cannot_be_empty': 'LDAP 地址不能为空',
|
||||
'dn_cannot_be_empty': 'LDAP DN不能为空',
|
||||
'ou_cannot_be_empty': 'LDAP OU不能为空',
|
||||
'filter_cannot_be_empty': 'LDAP 用户过滤器不能为空',
|
||||
'password_cannot_be_empty': 'LDAP 密码不能为空',
|
||||
},
|
||||
schedule: {
|
||||
|
|
|
@ -609,7 +609,7 @@ export default {
|
|||
'input_username': '請輸入用戶名',
|
||||
'input_url_placeholder': '請輸入LDAP地址 (如 ldap://localhost:389)',
|
||||
'input_ou_placeholder': '輸入用戶OU (使用|分隔各OU)',
|
||||
'input_filter_placeholder': '輸入過濾器 [可能的選項是cn或uid或sAMAccountName=%(user)s]',
|
||||
'input_filter_placeholder': '輸入過濾器 [可能的選項是cn或uid或sAMAccountName={0}, 如:(uid={0})]',
|
||||
'test_connect': '測試連接',
|
||||
'test_login': '測試登錄',
|
||||
'edit': '編輯',
|
||||
|
@ -617,6 +617,7 @@ export default {
|
|||
'url_cannot_be_empty': 'LDAP 地址不能為空',
|
||||
'dn_cannot_be_empty': 'LDAP DN不能為空',
|
||||
'ou_cannot_be_empty': 'LDAP OU不能為空',
|
||||
'filter_cannot_be_empty': 'LDAP 用戶過濾器不能為空',
|
||||
'password_cannot_be_empty': 'LDAP 密碼不能為空',
|
||||
},
|
||||
schedule: {
|
||||
|
|
Loading…
Reference in New Issue