refactor(系统设置): 系统参数认证配置移动至xpack
This commit is contained in:
parent
ef80edaf86
commit
579c6e4015
|
@ -1,105 +0,0 @@
|
|||
package io.metersphere.system.controller;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.system.dto.sdk.BasePageRequest;
|
||||
import io.metersphere.system.ldap.service.LdapService;
|
||||
import io.metersphere.system.ldap.vo.LdapLoginRequest;
|
||||
import io.metersphere.system.ldap.vo.LdapRequest;
|
||||
import io.metersphere.system.log.annotation.Log;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.utils.PageUtils;
|
||||
import io.metersphere.system.utils.Pager;
|
||||
import io.metersphere.system.domain.AuthSource;
|
||||
import io.metersphere.system.dto.AuthSourceDTO;
|
||||
import io.metersphere.system.dto.request.AuthSourceRequest;
|
||||
import io.metersphere.system.dto.request.AuthSourceStatusRequest;
|
||||
import io.metersphere.system.service.AuthSourceLogService;
|
||||
import io.metersphere.system.service.AuthSourceService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "系统设置-系统-系统参数-认证设置")
|
||||
@RestController
|
||||
@RequestMapping("/system/authsource")
|
||||
@Data
|
||||
public class AuthSourceController {
|
||||
@Resource
|
||||
private AuthSourceService authSourceService;
|
||||
|
||||
@Resource
|
||||
private LdapService ldapService;
|
||||
|
||||
@PostMapping("/list")
|
||||
@Operation(summary = "系统设置-系统-系统参数-认证设置-列表查询")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_PARAMETER_SETTING_AUTH_READ)
|
||||
public Pager<List<AuthSource>> list(@Validated @RequestBody BasePageRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
|
||||
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "create_time desc");
|
||||
return PageUtils.setPageInfo(page, authSourceService.list());
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
@Operation(summary = "系统设置-系统-系统参数-认证设置-新增")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_PARAMETER_SETTING_AUTH_READ_ADD)
|
||||
@Log(type = OperationLogType.ADD, expression = "#msClass.addLog(#authSource)", msClass = AuthSourceLogService.class)
|
||||
public AuthSource add(@Validated @RequestBody AuthSourceRequest authSource) {
|
||||
return authSourceService.addAuthSource(authSource);
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "系统设置-系统-系统参数-认证设置-更新")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_PARAMETER_SETTING_AUTH_READ_UPDATE)
|
||||
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#authSource)", msClass = AuthSourceLogService.class)
|
||||
public AuthSourceRequest update(@Validated @RequestBody AuthSourceRequest authSource) {
|
||||
return authSourceService.updateAuthSource(authSource);
|
||||
}
|
||||
|
||||
@GetMapping("/get/{id}")
|
||||
@Operation(summary = "系统设置-系统-系统参数-认证设置-详细信息")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_PARAMETER_SETTING_AUTH_READ)
|
||||
public AuthSourceDTO get(@PathVariable(value = "id") String id) {
|
||||
return authSourceService.getAuthSource(id);
|
||||
}
|
||||
|
||||
@GetMapping("/delete/{id}")
|
||||
@Operation(summary = "系统设置-系统-系统参数-认证设置-删除")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_PARAMETER_SETTING_AUTH_READ_DELETE)
|
||||
@Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#id)", msClass = AuthSourceLogService.class)
|
||||
public void delete(@PathVariable(value = "id") String id) {
|
||||
authSourceService.deleteAuthSource(id);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/update/status")
|
||||
@Operation(summary = "系统设置-系统-系统参数-认证设置-更新状态")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_PARAMETER_SETTING_AUTH_READ_UPDATE)
|
||||
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#request.getId())", msClass = AuthSourceLogService.class)
|
||||
public AuthSource updateStatus(@Validated @RequestBody AuthSourceStatusRequest request) {
|
||||
return authSourceService.updateStatus(request.getId(), request.getEnable());
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/ldap/test-connect")
|
||||
@Operation(summary = "系统设置-系统-系统参数-认证设置-ldap测试连接")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_PARAMETER_SETTING_AUTH_READ_UPDATE)
|
||||
public void ldapTestConnect(@Validated @RequestBody LdapRequest request) {
|
||||
ldapService.testConnect(request);
|
||||
}
|
||||
|
||||
@PostMapping("/ldap/test-login")
|
||||
@Operation(summary = "系统设置-系统-系统参数-认证设置-ldap测试登录")
|
||||
@RequiresPermissions(PermissionConstants.SYSTEM_PARAMETER_SETTING_AUTH_READ_UPDATE)
|
||||
public void testLogin(@RequestBody LdapLoginRequest request) {
|
||||
ldapService.testLogin(request);
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package io.metersphere.system.dto.request;
|
||||
|
||||
import io.metersphere.validation.groups.Created;
|
||||
import io.metersphere.validation.groups.Updated;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class AuthSourceRequest implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "认证源ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Size(min = 1, max = 50, message = "{auth_source.id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String id;
|
||||
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{authsource_name_is_null}")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "类型")
|
||||
@NotBlank(message = "{authsource_type_is_null}")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "认证源配置", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{authsource_configuration_is_null}", groups = {Created.class})
|
||||
private String configuration;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package io.metersphere.system.dto.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class AuthSourceStatusRequest implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@Schema(description = "是否禁用")
|
||||
private Boolean enable;
|
||||
|
||||
@Schema(description = "id")
|
||||
private String id;
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
package io.metersphere.system.ldap;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
public class CustomSSLSocketFactory extends SSLSocketFactory {
|
||||
private SSLSocketFactory socketFactory;
|
||||
|
||||
public CustomSSLSocketFactory() {
|
||||
try {
|
||||
SSLContext ctx = SSLContext.getInstance("TLS");
|
||||
ctx.init(null, new TrustManager[]{new DummyTrustmanager()}, new SecureRandom());
|
||||
socketFactory = ctx.getSocketFactory();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
public static SocketFactory getDefault() {
|
||||
return new CustomSSLSocketFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return socketFactory.getDefaultCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return socketFactory.getSupportedCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket socket, String string, int num, boolean bool) throws IOException {
|
||||
return socketFactory.createSocket(socket, string, num, bool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String string, int num) throws IOException, UnknownHostException {
|
||||
return socketFactory.createSocket(string, num);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String string, int num, InetAddress netAdd, int i) throws IOException, UnknownHostException {
|
||||
return socketFactory.createSocket(string, num, netAdd, i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress netAdd, int num) throws IOException {
|
||||
return socketFactory.createSocket(netAdd, num);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress netAdd1, int num, InetAddress netAdd2, int i) throws IOException {
|
||||
return socketFactory.createSocket(netAdd1, num, netAdd2, i);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 证书
|
||||
*/
|
||||
public static class DummyTrustmanager implements X509TrustManager {
|
||||
public void checkClientTrusted(X509Certificate[] cert, String string) throws CertificateException {
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] cert, String string) throws CertificateException {
|
||||
}
|
||||
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[0];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package io.metersphere.system.ldap;
|
||||
|
||||
import org.springframework.ldap.core.support.LdapContextSource;
|
||||
|
||||
import javax.naming.Context;
|
||||
import java.util.Hashtable;
|
||||
|
||||
public class SSLLdapContextSource extends LdapContextSource {
|
||||
public Hashtable<String, Object> getAnonymousEnv() {
|
||||
Hashtable<String, Object> anonymousEnv = super.getAnonymousEnv();
|
||||
anonymousEnv.put("java.naming.security.protocol", "ssl");
|
||||
anonymousEnv.put("java.naming.ldap.factory.socket", CustomSSLSocketFactory.class.getName());
|
||||
anonymousEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
||||
return anonymousEnv;
|
||||
}
|
||||
}
|
|
@ -1,162 +0,0 @@
|
|||
package io.metersphere.system.ldap.service;
|
||||
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.system.ldap.SSLLdapContextSource;
|
||||
import io.metersphere.system.ldap.vo.LdapLoginRequest;
|
||||
import io.metersphere.system.ldap.vo.LdapRequest;
|
||||
import io.metersphere.sdk.util.*;
|
||||
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.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.transaction.annotation.Transactional;
|
||||
|
||||
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
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class LdapService {
|
||||
|
||||
|
||||
public void testConnect(LdapRequest request) {
|
||||
getConnect(request);
|
||||
}
|
||||
|
||||
private LdapTemplate getConnect(LdapRequest request) {
|
||||
String credentials = EncryptUtils.aesDecrypt(request.getLdapPassword()).toString();
|
||||
LdapContextSource sourceLdapCtx;
|
||||
if (StringUtils.startsWithIgnoreCase(request.getLdapUrl(), "ldaps://")) {
|
||||
sourceLdapCtx = new SSLLdapContextSource();
|
||||
// todo 这里加上strategy 会报错
|
||||
} else {
|
||||
sourceLdapCtx = new LdapContextSource();
|
||||
}
|
||||
sourceLdapCtx.setUrl(request.getLdapUrl());
|
||||
sourceLdapCtx.setUserDn(request.getLdapDn());
|
||||
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());
|
||||
try {
|
||||
authenticate(request.getLdapDn(), credentials, ldapTemplate);
|
||||
} catch (AuthenticationException e) {
|
||||
LogUtils.error(e.getMessage(), e);
|
||||
throw new MSException(Translator.get("ldap_connect_fail_user"));
|
||||
} catch (Exception e) {
|
||||
LogUtils.error(e.getMessage(), e);
|
||||
throw new MSException(Translator.get("ldap_connect_fail"));
|
||||
}
|
||||
return 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试登录
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public DirContextOperations testLogin(LdapLoginRequest request) {
|
||||
String credentials = request.getPassword();
|
||||
DirContextOperations dirContextOperations = null;
|
||||
|
||||
try {
|
||||
LdapTemplate ldapTemplate = getLdapTemplate(request);
|
||||
// 获取LDAP用户相关信息
|
||||
dirContextOperations = getContextMapper(request, ldapTemplate);
|
||||
// 执行登录认证
|
||||
authenticate(String.valueOf(dirContextOperations.getDn()), credentials, ldapTemplate);
|
||||
} catch (AuthenticationException e) {
|
||||
LogUtils.error(e.getMessage(), e);
|
||||
throw new MSException(Translator.get("authentication_failed"));
|
||||
}
|
||||
|
||||
// 检查属性是否存在
|
||||
getMappingAttr("name", dirContextOperations, request);
|
||||
return dirContextOperations;
|
||||
}
|
||||
|
||||
private LdapTemplate getLdapTemplate(LdapLoginRequest request) {
|
||||
LdapRequest ldapRequest = new LdapRequest();
|
||||
BeanUtils.copyBean(ldapRequest, request);
|
||||
LdapTemplate ldapTemplate = getConnect(ldapRequest);
|
||||
return ldapTemplate;
|
||||
}
|
||||
|
||||
|
||||
public String getMappingAttr(String attr, DirContextOperations dirContext, LdapLoginRequest request) {
|
||||
// 检查LDAP映射属性
|
||||
String mapping = request.getLdapUserMapping();
|
||||
Map jsonObject = JSON.parseObject(mapping, Map.class);
|
||||
String mapAttr = (String) jsonObject.get(attr);
|
||||
String result = dirContext.getStringAttribute(mapAttr);
|
||||
return result;
|
||||
}
|
||||
|
||||
public DirContextOperations getContextMapper(LdapLoginRequest request, LdapTemplate ldapTemplate) {
|
||||
String filter = request.getLdapUserFilter();
|
||||
String[] arr = request.getLdapUserOu().split("|");
|
||||
|
||||
List<DirContextOperations> result = null;
|
||||
// 多OU
|
||||
for (String ou : arr) {
|
||||
try {
|
||||
result = ldapTemplate.search(query().base(ou.trim()).filter(filter, request.getUsername()), new MsContextMapper());
|
||||
if (result.size() == 1) {
|
||||
return result.get(0);
|
||||
}
|
||||
} catch (NameNotFoundException | InvalidNameException e) {
|
||||
LogUtils.error(e.getMessage(), e);
|
||||
throw new MSException(Translator.get("login_fail_ou_error"));
|
||||
} catch (InvalidSearchFilterException e) {
|
||||
LogUtils.error(e.getMessage(), e);
|
||||
throw new MSException(Translator.get("login_fail_filter_error"));
|
||||
}
|
||||
}
|
||||
|
||||
if (result.size() != 1) {
|
||||
throw new MSException(Translator.get("user_not_found_or_not_unique"));
|
||||
}
|
||||
|
||||
return result.get(0);
|
||||
}
|
||||
|
||||
private static class MsContextMapper extends AbstractContextMapper<DirContextOperations> {
|
||||
@Override
|
||||
public DirContextOperations doMapFromContext(DirContextOperations context) {
|
||||
return context;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package io.metersphere.system.ldap.vo;
|
||||
|
||||
import io.metersphere.system.dto.sdk.LoginRequest;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class LdapLoginRequest extends LoginRequest implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "LDAP地址", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{ldap_url_is_null}")
|
||||
private String ldapUrl;
|
||||
|
||||
@Schema(description = "LDAP绑定DN", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{ldap_dn_is_null}")
|
||||
private String ldapDn;
|
||||
|
||||
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{ldap_password_is_null}")
|
||||
private String ldapPassword;
|
||||
|
||||
@Schema(description = "用户过滤器", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{ldap_user_filter_is_null}")
|
||||
private String ldapUserFilter;
|
||||
|
||||
@Schema(description = "用户OU", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{ldap_ou_is_null}")
|
||||
private String ldapUserOu;
|
||||
|
||||
@Schema(description = "LDAP属性映射", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{ldap_user_mapping_is_null}")
|
||||
private String ldapUserMapping;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package io.metersphere.system.ldap.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class LdapRequest implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "LDAP地址", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{ldap_url_is_null}")
|
||||
private String ldapUrl;
|
||||
|
||||
@Schema(description = "LDAP绑定DN", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{ldap_dn_is_null}")
|
||||
private String ldapDn;
|
||||
|
||||
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{ldap_password_is_null}")
|
||||
private String ldapPassword;
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
package io.metersphere.system.service;
|
||||
|
||||
|
||||
import io.metersphere.sdk.constants.OperationLogConstants;
|
||||
import io.metersphere.system.log.dto.LogDTO;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.domain.AuthSource;
|
||||
import io.metersphere.system.mapper.AuthSourceMapper;
|
||||
import io.metersphere.system.dto.request.AuthSourceRequest;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class AuthSourceLogService {
|
||||
@Resource
|
||||
private AuthSourceMapper authSourceMapper;
|
||||
|
||||
/**
|
||||
* 添加接口日志
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public LogDTO addLog(AuthSourceRequest request) {
|
||||
LogDTO dto = new LogDTO(
|
||||
OperationLogConstants.SYSTEM,
|
||||
OperationLogConstants.SYSTEM,
|
||||
request.getId(),
|
||||
null,
|
||||
OperationLogType.ADD.name(),
|
||||
OperationLogModule.SETTING_SYSTEM_PARAMETER_AUTH_CONFIG,
|
||||
request.getName());
|
||||
|
||||
dto.setModifiedValue(JSON.toJSONBytes(request));
|
||||
return dto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改接口日志
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public LogDTO updateLog(AuthSourceRequest request) {
|
||||
AuthSource authSource = authSourceMapper.selectByPrimaryKey(request.getId());
|
||||
LogDTO dto = null;
|
||||
if (authSource != null) {
|
||||
dto = new LogDTO(
|
||||
OperationLogConstants.SYSTEM,
|
||||
OperationLogConstants.SYSTEM,
|
||||
request.getId(),
|
||||
null,
|
||||
OperationLogType.UPDATE.name(),
|
||||
OperationLogModule.SETTING_SYSTEM_PARAMETER_AUTH_CONFIG,
|
||||
request.getName());
|
||||
|
||||
dto.setOriginalValue(JSON.toJSONBytes(authSource));
|
||||
}
|
||||
return dto;
|
||||
}
|
||||
|
||||
public LogDTO updateLog(String id) {
|
||||
AuthSource authSource = authSourceMapper.selectByPrimaryKey(id);
|
||||
LogDTO dto = null;
|
||||
if (authSource != null) {
|
||||
dto = new LogDTO(
|
||||
OperationLogConstants.SYSTEM,
|
||||
OperationLogConstants.SYSTEM,
|
||||
id,
|
||||
null,
|
||||
OperationLogType.UPDATE.name(),
|
||||
OperationLogModule.SETTING_SYSTEM_PARAMETER_AUTH_CONFIG,
|
||||
authSource.getName());
|
||||
|
||||
dto.setOriginalValue(JSON.toJSONBytes(authSource));
|
||||
}
|
||||
return dto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除接口日志
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public LogDTO deleteLog(String id) {
|
||||
AuthSource authSource = authSourceMapper.selectByPrimaryKey(id);
|
||||
if (authSource == null) {
|
||||
return null;
|
||||
}
|
||||
LogDTO dto = new LogDTO(
|
||||
OperationLogConstants.SYSTEM,
|
||||
OperationLogConstants.SYSTEM,
|
||||
authSource.getId(),
|
||||
null,
|
||||
OperationLogType.DELETE.name(),
|
||||
OperationLogModule.SETTING_SYSTEM_PARAMETER_AUTH_CONFIG,
|
||||
authSource.getName());
|
||||
|
||||
dto.setOriginalValue(JSON.toJSONBytes(authSource));
|
||||
return dto;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
package io.metersphere.system.service;
|
||||
|
||||
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.BeanUtils;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.domain.AuthSource;
|
||||
import io.metersphere.system.domain.AuthSourceExample;
|
||||
import io.metersphere.system.dto.AuthSourceDTO;
|
||||
import io.metersphere.system.dto.request.AuthSourceRequest;
|
||||
import io.metersphere.system.mapper.AuthSourceMapper;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class AuthSourceService {
|
||||
@Resource
|
||||
private AuthSourceMapper authSourceMapper;
|
||||
|
||||
public List<AuthSource> list() {
|
||||
AuthSourceExample example = new AuthSourceExample();
|
||||
return authSourceMapper.selectByExample(example);
|
||||
}
|
||||
|
||||
public AuthSource addAuthSource(AuthSourceRequest authSource) {
|
||||
checkAuthSource(authSource);
|
||||
AuthSource source = delRequestToDB(authSource);
|
||||
authSourceMapper.insertSelective(source);
|
||||
return source;
|
||||
}
|
||||
|
||||
private AuthSource delRequestToDB(AuthSourceRequest authSource) {
|
||||
long createTime = System.currentTimeMillis();
|
||||
AuthSource source = new AuthSource();
|
||||
source.setName(authSource.getName());
|
||||
source.setConfiguration(authSource.getConfiguration().getBytes(StandardCharsets.UTF_8));
|
||||
source.setDescription(authSource.getDescription());
|
||||
source.setType(authSource.getType());
|
||||
source.setCreateTime(createTime);
|
||||
source.setUpdateTime(createTime);
|
||||
source.setId(IDGenerator.nextStr());
|
||||
return source;
|
||||
}
|
||||
|
||||
public void checkAuthSource(AuthSourceRequest authSource) {
|
||||
String resourcePoolName = authSource.getName();
|
||||
|
||||
AuthSourceExample example = new AuthSourceExample();
|
||||
AuthSourceExample.Criteria criteria = example.createCriteria();
|
||||
criteria.andNameEqualTo(resourcePoolName);
|
||||
if (StringUtils.isNotBlank(authSource.getId())) {
|
||||
criteria.andIdNotEqualTo(authSource.getId());
|
||||
}
|
||||
|
||||
if (authSourceMapper.countByExample(example) > 0) {
|
||||
throw new MSException(Translator.get("authsource_name_already_exists"));
|
||||
}
|
||||
if (StringUtils.isBlank(authSource.getConfiguration().toString())) {
|
||||
throw new MSException(Translator.get("authsource_configuration_is_null"));
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteAuthSource(String id) {
|
||||
authSourceMapper.deleteByPrimaryKey(id);
|
||||
}
|
||||
|
||||
public AuthSourceDTO getAuthSource(String id) {
|
||||
AuthSource source = authSourceMapper.selectByPrimaryKey(id);
|
||||
AuthSourceDTO authSourceDTO = new AuthSourceDTO();
|
||||
BeanUtils.copyBean(authSourceDTO, source);
|
||||
authSourceDTO.setConfiguration(new String(source.getConfiguration(), StandardCharsets.UTF_8));
|
||||
return authSourceDTO;
|
||||
}
|
||||
|
||||
public AuthSourceRequest updateAuthSource(AuthSourceRequest authSource) {
|
||||
checkAuthSource(authSource);
|
||||
AuthSource source = authSourceMapper.selectByPrimaryKey(authSource.getId());
|
||||
if (source != null) {
|
||||
source.setName(authSource.getName());
|
||||
source.setDescription(authSource.getDescription());
|
||||
source.setConfiguration(authSource.getConfiguration().getBytes());
|
||||
source.setType(authSource.getType());
|
||||
source.setUpdateTime(System.currentTimeMillis());
|
||||
authSourceMapper.updateByPrimaryKeySelective(source);
|
||||
}
|
||||
return authSource;
|
||||
}
|
||||
|
||||
public AuthSource updateStatus(String id, Boolean status) {
|
||||
if (BooleanUtils.isTrue(status)) {
|
||||
AuthSource authSource = authSourceMapper.selectByPrimaryKey(id);
|
||||
AuthSourceExample example = new AuthSourceExample();
|
||||
example.createCriteria().andIdNotEqualTo(id).andTypeEqualTo(authSource.getType()).andEnableEqualTo(true);
|
||||
List<AuthSource> authSources = authSourceMapper.selectByExample(example);
|
||||
if (CollectionUtils.isNotEmpty(authSources)) {
|
||||
AuthSource source = authSources.get(0);
|
||||
source.setEnable(false);
|
||||
authSourceMapper.updateByPrimaryKeySelective(source);
|
||||
}
|
||||
}
|
||||
AuthSource record = new AuthSource();
|
||||
record.setId(id);
|
||||
record.setEnable(BooleanUtils.toBooleanDefaultIfNull(status, false));
|
||||
record.setUpdateTime(System.currentTimeMillis());
|
||||
authSourceMapper.updateByPrimaryKeySelective(record);
|
||||
return record;
|
||||
}
|
||||
}
|
|
@ -1,251 +0,0 @@
|
|||
package io.metersphere.system.controller;
|
||||
|
||||
import io.metersphere.system.base.BaseTest;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.sdk.constants.SessionConstants;
|
||||
import io.metersphere.system.controller.handler.ResultHolder;
|
||||
import io.metersphere.system.dto.sdk.BasePageRequest;
|
||||
import io.metersphere.system.ldap.service.LdapService;
|
||||
import io.metersphere.system.ldap.vo.LdapLoginRequest;
|
||||
import io.metersphere.system.ldap.vo.LdapRequest;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.utils.Pager;
|
||||
import io.metersphere.system.domain.AuthSource;
|
||||
import io.metersphere.system.dto.request.AuthSourceRequest;
|
||||
import io.metersphere.system.dto.request.AuthSourceStatusRequest;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.ldap.core.DirContextAdapter;
|
||||
import org.springframework.ldap.core.DirContextOperations;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.jdbc.SqlConfig;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.ResultMatcher;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@AutoConfigureMockMvc
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
public class AuthSourceControllerTests extends BaseTest {
|
||||
|
||||
public static final String AUTH_SOURCE_ADD = "/system/authsource/add";
|
||||
|
||||
public static final String AUTH_SOURCE_LIST = "/system/authsource/list";
|
||||
|
||||
public static final String AUTH_SOURCE_UPDATE = "/system/authsource/update";
|
||||
|
||||
public static final String AUTH_SOURCE_GET = "/system/authsource/get/";
|
||||
|
||||
public static final String AUTH_SOURCE_DELETE = "/system/authsource/delete/";
|
||||
|
||||
private static final ResultMatcher CLIENT_ERROR_MATCHER = status().is4xxClientError();
|
||||
|
||||
public static final String AUTH_SOURCE_UPDATE_STATUS = "/system/authsource/update/status";
|
||||
|
||||
private static final ResultMatcher ERROR_REQUEST_MATCHER = status().is5xxServerError();
|
||||
|
||||
public static final String LDAP_TEST_CONNECT = "/system/authsource/ldap/test-connect";
|
||||
|
||||
public static final String LDAP_TEST_LOGIN = "/system/authsource/ldap/test-login";
|
||||
|
||||
@Mock
|
||||
private LdapService ldapService;
|
||||
@Resource
|
||||
AuthSourceController authSourceController;
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
public void testAddSource() throws Exception {
|
||||
AuthSourceRequest authSource = new AuthSourceRequest();
|
||||
authSource.setName("测试CAS");
|
||||
authSource.setType("CAS");
|
||||
this.requestPost(AUTH_SOURCE_ADD, authSource, ERROR_REQUEST_MATCHER);
|
||||
authSource.setConfiguration("123");
|
||||
this.requestPost(AUTH_SOURCE_ADD, authSource);
|
||||
|
||||
// @@校验权限
|
||||
requestPostPermissionTest(PermissionConstants.SYSTEM_PARAMETER_SETTING_AUTH_READ_ADD, AUTH_SOURCE_ADD, authSource);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
public void testGetSourceList() throws Exception {
|
||||
BasePageRequest basePageRequest = new BasePageRequest();
|
||||
basePageRequest.setCurrent(1);
|
||||
basePageRequest.setPageSize(10);
|
||||
this.requestPost(AUTH_SOURCE_LIST, basePageRequest);
|
||||
basePageRequest.setSort(new HashMap<>() {{
|
||||
put("createTime", "desc");
|
||||
}});
|
||||
this.requestPost(AUTH_SOURCE_LIST, basePageRequest);
|
||||
|
||||
requestPostPermissionTest(PermissionConstants.SYSTEM_PARAMETER_SETTING_AUTH_READ, AUTH_SOURCE_LIST, basePageRequest);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Order(3)
|
||||
public void testUpdateSource() throws Exception {
|
||||
List<AuthSourceRequest> authSourceList = this.getAuthSourceList();
|
||||
AuthSourceRequest authSource = new AuthSourceRequest();
|
||||
authSource.setId("authsource_id");
|
||||
authSource.setConfiguration("123666");
|
||||
authSource.setName("更新");
|
||||
authSource.setType("CAS");
|
||||
this.requestPost(AUTH_SOURCE_UPDATE, authSource);
|
||||
authSource.setId(authSourceList.get(0).getId());
|
||||
|
||||
requestPostPermissionTest(PermissionConstants.SYSTEM_PARAMETER_SETTING_AUTH_READ_UPDATE, AUTH_SOURCE_UPDATE, authSource);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(4)
|
||||
@Sql(scripts = {"/dml/init_auth_source_test.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED))
|
||||
public void testUpdateStatus() throws Exception {
|
||||
|
||||
List<AuthSourceRequest> authSourceList = this.getAuthSourceList();
|
||||
AuthSourceStatusRequest request = new AuthSourceStatusRequest();
|
||||
request.setId(authSourceList.get(0).getId());
|
||||
this.requestPost(AUTH_SOURCE_UPDATE_STATUS, request);
|
||||
request.setEnable(false);
|
||||
this.requestPost(AUTH_SOURCE_UPDATE_STATUS, request);
|
||||
requestPostPermissionTest(PermissionConstants.SYSTEM_PARAMETER_SETTING_AUTH_READ_UPDATE, AUTH_SOURCE_UPDATE_STATUS, request);
|
||||
request.setEnable(true);
|
||||
this.requestPost(AUTH_SOURCE_UPDATE_STATUS, request);
|
||||
|
||||
request.setId("wx_test_1");
|
||||
request.setEnable(true);
|
||||
this.requestPost(AUTH_SOURCE_UPDATE_STATUS, request);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Order(5)
|
||||
public void testGetSourceById() throws Exception {
|
||||
List<AuthSourceRequest> authSourceList = this.getAuthSourceList();
|
||||
String url = AUTH_SOURCE_GET + authSourceList.get(0).getId();
|
||||
this.requestGet(url);
|
||||
|
||||
requestGetPermissionTest(PermissionConstants.SYSTEM_PARAMETER_SETTING_AUTH_READ, url);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Order(6)
|
||||
public void testDelSourceById() throws Exception {
|
||||
List<AuthSourceRequest> authSourceList = this.getAuthSourceList();
|
||||
String url = AUTH_SOURCE_DELETE + authSourceList.get(0).getId();
|
||||
this.requestGet(url);
|
||||
|
||||
requestGetPermissionTest(PermissionConstants.SYSTEM_PARAMETER_SETTING_AUTH_READ_DELETE, url);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Order(7)
|
||||
public void testAddSourceError() throws Exception {
|
||||
AuthSource authSource = new AuthSource();
|
||||
authSource.setConfiguration("123".getBytes());
|
||||
this.requestPost(AUTH_SOURCE_ADD, authSource, CLIENT_ERROR_MATCHER);
|
||||
}
|
||||
|
||||
|
||||
private MvcResult requestPost(String url, Object param) throws Exception {
|
||||
return mockMvc.perform(MockMvcRequestBuilders.post(url)
|
||||
.header(SessionConstants.HEADER_TOKEN, sessionId)
|
||||
.header(SessionConstants.CSRF_TOKEN, csrfToken)
|
||||
.content(JSON.toJSONString(param))
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
|
||||
.andReturn();
|
||||
}
|
||||
|
||||
private MvcResult requestGet(String url) throws Exception {
|
||||
return mockMvc.perform(MockMvcRequestBuilders.get(url)
|
||||
.header(SessionConstants.HEADER_TOKEN, sessionId)
|
||||
.header(SessionConstants.CSRF_TOKEN, csrfToken))
|
||||
.andExpect(status().isOk()).andReturn();
|
||||
}
|
||||
|
||||
private List<AuthSourceRequest> getAuthSourceList() throws Exception {
|
||||
BasePageRequest basePageRequest = new BasePageRequest();
|
||||
basePageRequest.setCurrent(1);
|
||||
basePageRequest.setPageSize(10);
|
||||
MvcResult mvcResult = this.requestPost(AUTH_SOURCE_LIST, basePageRequest);
|
||||
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
Pager<?> returnPager = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
|
||||
List<AuthSourceRequest> authSourceRequests = JSON.parseArray(JSON.toJSONString(returnPager.getList()), AuthSourceRequest.class);
|
||||
return authSourceRequests;
|
||||
}
|
||||
|
||||
private void requestPost(String url, Object param, ResultMatcher resultMatcher) throws Exception {
|
||||
mockMvc.perform(MockMvcRequestBuilders.post(url)
|
||||
.header(SessionConstants.HEADER_TOKEN, sessionId)
|
||||
.header(SessionConstants.CSRF_TOKEN, csrfToken)
|
||||
.content(JSON.toJSONString(param))
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(resultMatcher)
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Order(11)
|
||||
public void testLdapConnectMock() throws Exception {
|
||||
authSourceController.setLdapService(ldapService);
|
||||
LdapRequest ldapRequest = getRequest("ldaps://127.1.1.1", "cn=admin,dc=example,dc=org", "admin");
|
||||
Mockito.doNothing().when(ldapService).testConnect(ldapRequest);
|
||||
this.requestPostAndReturn(LDAP_TEST_CONNECT, ldapRequest);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(12)
|
||||
public void testLdapLoginMock() throws Exception {
|
||||
authSourceController.setLdapService(ldapService);
|
||||
LdapLoginRequest loginRequest = getLoginRequest("ldap://127.1.1.1", "cn=admin,dc=example,dc=org", "admin", "cn=admin,dc=example,dc=org", "(|(uid={0})(mail={0}))", "{\"username\":\"uid\",\"name\":\"cn\",\"email\":\"mail\"}", "admin", "admin");
|
||||
DirContextOperations operations = new DirContextAdapter();
|
||||
Mockito.when(ldapService.testLogin(loginRequest)).thenReturn(operations);
|
||||
this.requestPostAndReturn(LDAP_TEST_LOGIN, loginRequest);
|
||||
}
|
||||
|
||||
private LdapLoginRequest getLoginRequest(String ldapUrl, String ldapDn, String ldapPassword, String ldapUserOu, String ldapUserFilter, String ldapUserMapping, String username, String password) {
|
||||
LdapLoginRequest loginRequest = new LdapLoginRequest();
|
||||
loginRequest.setLdapUrl(ldapUrl);
|
||||
loginRequest.setLdapDn(ldapDn);
|
||||
loginRequest.setLdapPassword(ldapPassword);
|
||||
loginRequest.setLdapUserOu(ldapUserOu);
|
||||
loginRequest.setLdapUserFilter(ldapUserFilter);
|
||||
loginRequest.setLdapUserMapping(ldapUserMapping);
|
||||
loginRequest.setUsername(username);
|
||||
loginRequest.setPassword(password);
|
||||
return loginRequest;
|
||||
}
|
||||
|
||||
|
||||
private LdapRequest getRequest(String ldapUrl, String ldapDn, String ldapPassword) {
|
||||
LdapRequest ldapRequest = new LdapRequest();
|
||||
ldapRequest.setLdapUrl(ldapUrl);
|
||||
ldapRequest.setLdapDn(ldapDn);
|
||||
ldapRequest.setLdapPassword(ldapPassword);
|
||||
return ldapRequest;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue