feat(X-Pack): 新增LDAP认证

This commit is contained in:
fit2cloud-chenyw 2024-07-18 14:53:46 +08:00
parent 0987448644
commit bd0d7a9cdc
8 changed files with 100 additions and 20 deletions

View File

@ -111,8 +111,6 @@ service.interceptors.request.use(
;(config.headers as AxiosRequestHeaders)['X-DE-LINK-TOKEN'] = linkStore.getLinkToken
} else if (embeddedStore.token) {
;(config.headers as AxiosRequestHeaders)['X-EMBEDDED-TOKEN'] = embeddedStore.token
} else if (wsCache.get('de-ldap-token')) {
;(config.headers as AxiosRequestHeaders)['Authorization'] = wsCache.get('de-ldap-token')
}
if (wsCache.get('user.language')) {
const key = wsCache.get('user.language')

View File

@ -141,10 +141,14 @@ const ldapValidate = callback => {
if (!formRef.value) return
formRef.value.validate((valid: boolean) => {
if (valid && callback) {
duringLogin.value = true
callback()
}
})
}
const ldapFeedback = () => {
duringLogin.value = false
}
const activeType = ref('account')
const tablePaneList = ref([{ title: '普通登录', name: 'simple' }])
const xpackLoaded = info => {
@ -230,23 +234,28 @@ onMounted(async () => {
if (!checkPlatform()) {
const res = await loginCategoryApi()
const adminLogin = router.currentRoute?.value?.name === 'admin-login'
if (adminLogin && !res.data) {
if (adminLogin && (!res.data || res.data === 1)) {
router.push('/401')
return
}
if (res.data && !adminLogin) {
loadingText.value = '加载中...'
document.getElementsByClassName('ed-loading-text')?.length &&
(document.getElementsByClassName('ed-loading-text')[0]['innerText'] = loadingText.value)
nextTick(() => {
const param = { methodName: 'ssoLogin', args: res.data }
const timer = setInterval(() => {
if (xpackLoginHandler?.value.invokeMethod) {
xpackLoginHandler?.value.invokeMethod(param)
clearInterval(timer)
}
}, 1000)
})
if (res.data === 1) {
activeName.value = 'LDAP'
preheat.value = false
} else {
loadingText.value = '加载中...'
document.getElementsByClassName('ed-loading-text')?.length &&
(document.getElementsByClassName('ed-loading-text')[0]['innerText'] = loadingText.value)
nextTick(() => {
const param = { methodName: 'ssoLogin', args: res.data }
const timer = setInterval(() => {
if (xpackLoginHandler?.value.invokeMethod) {
xpackLoginHandler?.value.invokeMethod(param)
clearInterval(timer)
}
}, 1000)
})
}
} else {
preheat.value = false
}
@ -325,7 +334,9 @@ onMounted(async () => {
<XpackComponent
class="default-login-tabs"
:active-name="activeName"
:login-form="state.loginForm"
@validate="ldapValidate"
@feedback="ldapFeedback"
jsname="L2NvbXBvbmVudC9sb2dpbi9MZGFw"
/>

@ -1 +1 @@
Subproject commit e7fbd2e19945f1d35578b2e8e824bd605a49c8f6
Subproject commit d1d457a0c68f1f8c01b25e6533953b870ebe793a

View File

@ -2,10 +2,7 @@ package io.dataease.api.xpack.settings;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.api.xpack.settings.request.XpackAuthenticationEditor;
import io.dataease.api.xpack.settings.vo.XpackCasVO;
import io.dataease.api.xpack.settings.vo.XpackOidcVO;
import io.dataease.api.xpack.settings.vo.XpackAuthenticationStatusVO;
import io.dataease.api.xpack.settings.vo.XpackAuthenticationVO;
import io.dataease.api.xpack.settings.vo.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
@ -34,6 +31,9 @@ public interface XpackAuthenticationApi {
@PostMapping("/save/cas")
String saveCas(@RequestBody XpackCasVO editor);
@PostMapping("/save/ldap")
String saveLdap(@RequestBody XpackLdapVO editor);
@GetMapping("/info/oidc")
XpackOidcVO oidcInfo();
@ -41,6 +41,9 @@ public interface XpackAuthenticationApi {
@GetMapping("/info/cas")
XpackCasVO casInfo();
@GetMapping("/info/ldap")
XpackLdapVO ldapInfo();
@PostMapping("/validate/oidc")
String validateOidc(@RequestBody XpackOidcVO editor);
@ -48,6 +51,9 @@ public interface XpackAuthenticationApi {
@PostMapping("/validate/cas")
String validateCas(@RequestBody XpackCasVO editor);
@PostMapping("/validate/ldap")
String validateLdap(@RequestBody XpackLdapVO editor);
@PostMapping("/validateId/{id}")
String validate(@PathVariable("id") Long id);

View File

@ -0,0 +1,25 @@
package io.dataease.api.xpack.settings.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
public class XpackLdapVO implements Serializable {
@Serial
private static final long serialVersionUID = -2996803523472015035L;
private String addr;
private String dn;
private String pwd;
private String ou;
private String filter;
private String mapping;
}

View File

@ -11,4 +11,11 @@
<artifactId>api-permissions</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,5 +1,6 @@
package io.dataease.api.permissions.login.dto;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@ -15,4 +16,7 @@ public class PwdLoginDTO {
@Schema(description = "密码(需加密)", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "login.validator.pwd")
private String pwd;
@Hidden
private Integer origin = 0;
}

View File

@ -33,4 +33,33 @@ public class AesUtils {
throw new RuntimeException("decrypt errorplease check parameters", e);
}
}
public static String aesEncrypt(String src, String secretKey, String iv) {
if (StringUtils.isBlank(secretKey)) {
throw new RuntimeException("secretKey is empty");
}
try {
byte[] raw = secretKey.getBytes(UTF_8);
SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES");
// "算法/模式/补码方式" ECB
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec iv1 = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv1);
byte[] encrypted = cipher.doFinal(src.getBytes(UTF_8));
return Base64.encodeBase64String(encrypted);
} catch (Exception e) {
throw new RuntimeException("AES encrypt error:", e);
}
}
public static Object aesEncrypt(Object o) {
return o == null ? null : aesEncrypt(o.toString(), "www.fit2cloud.co", "1234567890123456");
}
public static Object aesDecrypt(Object o) {
return o == null ? null : aesDecrypt(o.toString(), "www.fit2cloud.co", "1234567890123456");
}
}