This is an automated email from the ASF dual-hosted git repository.

caishunfeng pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git


The following commit(s) were added to refs/heads/dev by this push:
     new 627c76b75a [Improvement-16106] Add admin-user-filter in LDAP (#16826)
627c76b75a is described below

commit 627c76b75a11afdae0b8b6656385a280aec4fdba
Author: xiangzihao <[email protected]>
AuthorDate: Fri Nov 22 17:39:18 2024 +0800

    [Improvement-16106] Add admin-user-filter in LDAP (#16826)
    
    * improvement 16106
    
    * fix ut
    
    * fix comment
    
    * fix spotless
---
 .github/workflows/api-test.yml                     |   2 +
 docs/docs/en/guide/security/authentication-type.md |  37 ++----
 docs/docs/zh/guide/security/authentication-type.md |  50 +++-----
 dolphinscheduler-api-test/README.md                |  26 +++++
 .../api/test/cases/ExecutorAPITest.java            |   2 +
 .../api/test/cases/LdapLoginAPITest.java           | 112 ++++++++++++++++++
 .../api/test/entity/GetUserInfoResponseData.java   |  35 ++++--
 .../api/test/pages/security/UserPage.java          |  22 ++--
 .../resources/docker/ldap-login}/application.yaml  |  19 +--
 .../docker/ldap-login/docker-compose.yaml          |  63 ++++++++++
 dolphinscheduler-api-test/pom.xml                  |   5 +-
 .../LdapLoginResult.java}                          |  22 ++--
 .../api/security/impl/AbstractAuthenticator.java   |   8 +-
 .../api/security/impl/ldap/LdapAuthenticator.java  |  11 +-
 .../api/security/impl/ldap/LdapService.java        | 129 ++++++++++++++-------
 .../security/impl/pwd/PasswordAuthenticator.java   |   4 +-
 .../security/impl/sso/CasdoorAuthenticator.java    |   6 +-
 .../src/main/resources/application.yaml            |  12 +-
 .../api/security/SecurityConfigLDAPTest.java       |   1 +
 .../security/impl/ldap/LdapAuthenticatorTest.java  |  20 ++--
 .../api/security/impl/ldap/LdapServiceTest.java    | 107 -----------------
 .../src/test/resources/application.yaml            |   9 +-
 .../src/main/resources/application.yaml            |  12 +-
 23 files changed, 427 insertions(+), 287 deletions(-)

diff --git a/.github/workflows/api-test.yml b/.github/workflows/api-test.yml
index fffebe801a..b31d431c28 100644
--- a/.github/workflows/api-test.yml
+++ b/.github/workflows/api-test.yml
@@ -115,6 +115,8 @@ jobs:
             class: org.apache.dolphinscheduler.api.test.cases.ExecutorAPITest
           - name: WorkflowInstanceAPITest
             class: 
org.apache.dolphinscheduler.api.test.cases.WorkflowInstanceAPITest
+          - name: LdapLoginAPITest
+            class: org.apache.dolphinscheduler.api.test.cases.LdapLoginAPITest
     env:
       RECORDING_PATH: /tmp/recording-${{ matrix.case.name }}
     steps:
diff --git a/docs/docs/en/guide/security/authentication-type.md 
b/docs/docs/en/guide/security/authentication-type.md
index 31c8d05de3..ae82f54976 100644
--- a/docs/docs/en/guide/security/authentication-type.md
+++ b/docs/docs/en/guide/security/authentication-type.md
@@ -10,21 +10,23 @@
 security:
   authentication:
     # Authentication types (supported types: PASSWORD,LDAP,CASDOOR_SSO)
-    type: PASSWORD
+    type: LDAP
     # IF you set type `LDAP`, below config will be effective
     ldap:
       # ldap server config
-      urls: ldap://ldap.forumsys.com:389/
+      url: ldap://ldap.forumsys.com:389/
       base-dn: dc=example,dc=com
-      username: cn=read-only-admin,dc=example,dc=com
+      username: cn=admin,dc=example,dc=com
       password: password
       user:
         # admin userId when you use LDAP login
-        admin: read-only-admin
+        admin: ldap-admin
+        # user search filter to find admin user
+        admin-user-filter: (&(cn={0}))
         identity-attribute: uid
         email-attribute: mail
         # action when ldap user is not exist (supported types: CREATE,DENY)
-        not-exist-action: CREATE
+        not-exist-action: DENY
       ssl:
         enable: false
         # jks file absolute path && password
@@ -71,31 +73,6 @@ casdoor:
    redirect-url: ""
 ```
 
-For detailed explanation of specific fields, please see: [Api-server related 
configuration](../../architecture/configuration.md)
-
-## LDAP Test
-
-We offer you a unit-test class while you can test the integration of 
DolphinScheduler with LDAP without running the service.
-
-> 
dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java
-
-You can follow guide below:
-- Change`TestPropertySource`configuration to your LDAP information.
-- Change userId && userPwd to your information in the `ldapLogin` method.
-- Change the expected email to the return value you expect in the `ldapLogin` 
method.
-- Run`ldapLogin`method and determine whether the LDAP login result is expected.
-
-If you want to enable ssl, please change configuration in `TestPropertySource` 
like below:
-
-```
-security.authentication.ldap.ssl.enable=false
-// absolute path
-security.authentication.ldap.ssl.trust-store=/ldapkeystore.jks
-security.authentication.ldap.ssl.trust-store-password=yourpassword
-```
-
-Then run`ldapLoginSSL`method and determine whether the LDAP login result is 
expected.
-
 ## Casdoor SSO
 
 [Casdoor](https://casdoor.org/) is a UI-first Identity Access Management (IAM) 
/ Single-Sign-On (SSO) platform based on OAuth 2.0, OIDC, SAML and CAS. You can 
add SSO capability to Dolphinscheduler through Casdoor by following these steps:
diff --git a/docs/docs/zh/guide/security/authentication-type.md 
b/docs/docs/zh/guide/security/authentication-type.md
index b32e13b46b..3a7b5a4772 100644
--- a/docs/docs/zh/guide/security/authentication-type.md
+++ b/docs/docs/zh/guide/security/authentication-type.md
@@ -14,22 +14,23 @@ security:
     # IF you set type `LDAP`, below config will be effective
     ldap:
       # ldap server config
-      urls: ldap://ldap.forumsys.com:389/
+      url: ldap://ldap.forumsys.com:389/
       base-dn: dc=example,dc=com
-      username: cn=read-only-admin,dc=example,dc=com
+      username: cn=admin,dc=example,dc=com
       password: password
       user:
-        # admin userId when you use LDAP login
-        admin: read-only-admin
-        identity-attribute: uid
-        email-attribute: mail
-        # action when ldap user is not exist (supported types: CREATE,DENY)
-        not-exist-action: CREATE
+         # admin userId when you use LDAP login
+         admin: ldap-admin
+         # user search filter to find admin user
+         identity-attribute: uid
+         email-attribute: mail
+         # action when ldap user is not exist (supported types: CREATE,DENY)
+         not-exist-action: DENY
       ssl:
-        enable: false
-        # jks file absolute path && password
-        trust-store: "/ldapkeystore.jks"
-        trust-store-password: "password"
+         enable: false
+         # jks file absolute path && password
+         trust-store: "/ldapkeystore.jks"
+         trust-store-password: "password"
     casdoor:
       user:
         admin: ""
@@ -71,31 +72,6 @@ casdoor:
    redirect-url: ""
 ```
 
-具体字段解释详见:[Api-server相关配置](../../architecture/configuration.md)
-
-## 开发者LDAP测试
-
-我们提供了一个单元测试类,可以在不启动项目的情况下测试DolphinScheduler与LDAP的集成。
-
-> 
dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java
-
-使用步骤如下:
-- 修改`TestPropertySource`配置参数为你的LDAP信息;
-- 修改`ldapLogin`方法中的userId和userPwd为你的账号密码;
-- 修改`ldapLogin`方法中的expected email为正常登陆的返回值;
-- 执行`ldapLogin`方法,判断LDAP登陆结果是否为预期;
-
-如果你要启用ssl,请修改`TestPropertySource`配置中ssl相关参数为:
-
-```
-security.authentication.ldap.ssl.enable=false
-// absolute path
-security.authentication.ldap.ssl.trust-store=/ldapkeystore.jks 
-security.authentication.ldap.ssl.trust-store-password=yourpassword
-```
-
-运行`ldapLoginSSL`方法,判断email是否为预期的返回值。
-
 ## 通过 Casdoor 实现 SSO 登录
 
 Casdoor 是基于 OAuth 2.0、OIDC、SAML 和 CAS 的面向 UI 
的身份访问管理(IAM)/单点登录(SSO)平台。您可以通过以下步骤通过 Casdoor 为 Dolphinscheduler 添加 SSO 功能:
diff --git a/dolphinscheduler-api-test/README.md 
b/dolphinscheduler-api-test/README.md
index 9e48bc6430..1db1196841 100644
--- a/dolphinscheduler-api-test/README.md
+++ b/dolphinscheduler-api-test/README.md
@@ -43,3 +43,29 @@ class TenantAPITest {
 }
 ```
 
+## Notes
+
+## Local development
+
+### Mac M1
+Add VM options to the test configuration in IntelliJ IDEA:
+```
+# In this mode you need to install docker desktop for mac and run it with 
locally
+-Dm1_chip=true
+```
+
+### Running locally(without Docker)
+```
+# In this mode you need to start frontend and backend services locally
+-Dlocal=true
+```
+
+### Running locally(with Docker)
+```
+# In this mode you only need to install docker locally
+```
+
+- To run the tests locally, you need to have the DolphinScheduler running 
locally. You should add `dolphinscheduler-api-test/pom.xml` to the maven project
+  Since it does not participate in project compilation, it is not in the main 
project.
+- Running run test class 
`org.apache.dolphinscheduler.api.test.cases.TenantAPITest` in the IDE.
+
diff --git 
a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/ExecutorAPITest.java
 
b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/ExecutorAPITest.java
index b9430546b0..bf1d05691a 100644
--- 
a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/ExecutorAPITest.java
+++ 
b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/ExecutorAPITest.java
@@ -47,10 +47,12 @@ import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Order;
 import org.junit.jupiter.api.Test;
+import org.junitpioneer.jupiter.DisableIfTestFails;
 
 //TODO: Some test cases rely on WorkflowInstance APIs. Should complete 
remaining cases after WorkflowInstance related API tests done.
 @DolphinScheduler(composeFiles = "docker/basic/docker-compose.yaml")
 @Slf4j
+@DisableIfTestFails
 public class ExecutorAPITest {
 
     private static final String username = "admin";
diff --git 
a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/LdapLoginAPITest.java
 
b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/LdapLoginAPITest.java
new file mode 100644
index 0000000000..f2b9e4cadc
--- /dev/null
+++ 
b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/cases/LdapLoginAPITest.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.api.test.cases;
+
+import org.apache.dolphinscheduler.api.test.core.DolphinScheduler;
+import org.apache.dolphinscheduler.api.test.entity.GetUserInfoResponseData;
+import org.apache.dolphinscheduler.api.test.entity.HttpResponse;
+import org.apache.dolphinscheduler.api.test.entity.LoginResponseData;
+import org.apache.dolphinscheduler.api.test.pages.LoginPage;
+import org.apache.dolphinscheduler.api.test.pages.security.UserPage;
+import org.apache.dolphinscheduler.api.test.utils.JSONUtils;
+import org.apache.dolphinscheduler.common.enums.UserType;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junitpioneer.jupiter.DisableIfTestFails;
+
+@DolphinScheduler(composeFiles = "docker/ldap-login/docker-compose.yaml")
+@Slf4j
+@DisableIfTestFails
+public class LdapLoginAPITest {
+
+    private static String sessionId;
+
+    @Test
+    @Order(10)
+    public void testAdminUserLoginSuccess() {
+        final String username = "admin_user01";
+
+        final String password = "123";
+
+        LoginPage loginPage = new LoginPage();
+        HttpResponse loginHttpResponse = loginPage.login(username, password);
+        sessionId =
+                JSONUtils.convertValue(loginHttpResponse.getBody().getData(), 
LoginResponseData.class).getSessionId();
+        UserPage userPage = new UserPage();
+        HttpResponse getUserInfoHttpResponse = userPage.getUserInfo(sessionId);
+        GetUserInfoResponseData getUserInfoResponseData =
+                
JSONUtils.convertValue(getUserInfoHttpResponse.getBody().getData(), 
GetUserInfoResponseData.class);
+        Assertions.assertEquals(username, 
getUserInfoResponseData.getUserName());
+        Assertions.assertEquals(UserType.ADMIN_USER, 
getUserInfoResponseData.getUserType());
+    }
+
+    @Test
+    @Order(20)
+    public void testAdminUserFilterLoginSuccess() {
+        final String username = "admin_user03";
+
+        final String password = "123";
+
+        LoginPage loginPage = new LoginPage();
+        HttpResponse loginHttpResponse = loginPage.login(username, password);
+        sessionId =
+                JSONUtils.convertValue(loginHttpResponse.getBody().getData(), 
LoginResponseData.class).getSessionId();
+        UserPage userPage = new UserPage();
+        HttpResponse getUserInfoHttpResponse = userPage.getUserInfo(sessionId);
+        GetUserInfoResponseData getUserInfoResponseData =
+                
JSONUtils.convertValue(getUserInfoHttpResponse.getBody().getData(), 
GetUserInfoResponseData.class);
+        Assertions.assertEquals(username, 
getUserInfoResponseData.getUserName());
+        Assertions.assertEquals(UserType.ADMIN_USER, 
getUserInfoResponseData.getUserType());
+    }
+
+    @Test
+    @Order(30)
+    public void testGeneralUserLoginSuccess() {
+        final String username = "general_user02";
+
+        final String password = "123";
+
+        LoginPage loginPage = new LoginPage();
+        HttpResponse loginHttpResponse = loginPage.login(username, password);
+        sessionId =
+                JSONUtils.convertValue(loginHttpResponse.getBody().getData(), 
LoginResponseData.class).getSessionId();
+        UserPage userPage = new UserPage();
+        HttpResponse getUserInfoHttpResponse = userPage.getUserInfo(sessionId);
+        GetUserInfoResponseData getUserInfoResponseData =
+                
JSONUtils.convertValue(getUserInfoHttpResponse.getBody().getData(), 
GetUserInfoResponseData.class);
+        Assertions.assertEquals(username, 
getUserInfoResponseData.getUserName());
+        Assertions.assertEquals(UserType.GENERAL_USER, 
getUserInfoResponseData.getUserType());
+    }
+
+    @Test
+    @Order(40)
+    public void testGeneralUserLoginFailed() {
+        final String username = "general_user02";
+
+        final String password = "1";
+
+        LoginPage loginPage = new LoginPage();
+        HttpResponse loginHttpResponse = loginPage.login(username, password);
+        Boolean loginResult = loginHttpResponse.getBody().getSuccess();
+        Assertions.assertFalse(loginResult);
+    }
+}
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java
 
b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/entity/GetUserInfoResponseData.java
similarity index 52%
copy from 
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java
copy to 
dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/entity/GetUserInfoResponseData.java
index a7ae0dd9f1..7b5db1ab96 100644
--- 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java
+++ 
b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/entity/GetUserInfoResponseData.java
@@ -15,15 +15,34 @@
  * limitations under the License.
  */
 
-package org.apache.dolphinscheduler.api.security.impl.pwd;
+package org.apache.dolphinscheduler.api.test.entity;
 
-import org.apache.dolphinscheduler.api.security.impl.AbstractAuthenticator;
-import org.apache.dolphinscheduler.dao.entity.User;
+import org.apache.dolphinscheduler.common.enums.UserType;
 
-public class PasswordAuthenticator extends AbstractAuthenticator {
+import java.util.Date;
 
-    @Override
-    public User login(String userId, String password) {
-        return userService.queryUser(userId, password);
-    }
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class GetUserInfoResponseData {
+
+    private Integer id;
+    private String userName;
+    private String userPassword;
+    private String email;
+    private Integer phone;
+    private UserType userType;
+    private Integer tenantId;
+    private Integer state;
+    private String tenantCode;
+    private String queueName;
+    private String alertGroup;
+    private String queue;
+    private String timeZone;
+    private Date createTime;
+    private Date updateTime;
 }
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java
 
b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/pages/security/UserPage.java
similarity index 56%
copy from 
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java
copy to 
dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/pages/security/UserPage.java
index a7ae0dd9f1..f667bcfcd0 100644
--- 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java
+++ 
b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/java/org/apache/dolphinscheduler/api/test/pages/security/UserPage.java
@@ -15,15 +15,23 @@
  * limitations under the License.
  */
 
-package org.apache.dolphinscheduler.api.security.impl.pwd;
+package org.apache.dolphinscheduler.api.test.pages.security;
 
-import org.apache.dolphinscheduler.api.security.impl.AbstractAuthenticator;
-import org.apache.dolphinscheduler.dao.entity.User;
+import org.apache.dolphinscheduler.api.test.core.Constants;
+import org.apache.dolphinscheduler.api.test.entity.HttpResponse;
+import org.apache.dolphinscheduler.api.test.utils.RequestClient;
 
-public class PasswordAuthenticator extends AbstractAuthenticator {
+import java.util.HashMap;
+import java.util.Map;
 
-    @Override
-    public User login(String userId, String password) {
-        return userService.queryUser(userId, password);
+public class UserPage {
+
+    public HttpResponse getUserInfo(String sessionId) {
+        Map<String, String> headers = new HashMap<>();
+        headers.put(Constants.SESSION_ID_KEY, sessionId);
+
+        RequestClient requestClient = new RequestClient();
+
+        return requestClient.get("/users/get-user-info", headers, new 
HashMap<>());
     }
 }
diff --git 
a/dolphinscheduler-standalone-server/src/main/resources/application.yaml 
b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/resources/docker/ldap-login/application.yaml
similarity index 97%
copy from dolphinscheduler-standalone-server/src/main/resources/application.yaml
copy to 
dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/resources/docker/ldap-login/application.yaml
index 97b9b6d22d..51d8e23c2f 100644
--- a/dolphinscheduler-standalone-server/src/main/resources/application.yaml
+++ 
b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/resources/docker/ldap-login/application.yaml
@@ -86,19 +86,20 @@ registry:
 security:
   authentication:
     # Authentication types (supported types: PASSWORD,LDAP,CASDOOR_SSO)
-    type: PASSWORD
+    type: LDAP
     # IF you set type `LDAP`, below config will be effective
     ldap:
       # ldap server config
-      urls: ldap://ldap.forumsys.com:389/
-      base-dn: dc=example,dc=com
-      username: cn=read-only-admin,dc=example,dc=com
-      password: password
+      url: ldap://openldap:1389/
+      base-dn: ou=users,dc=example,dc=org
+      username: cn=admin,dc=example,dc=org
+      password: adminpassword
       user:
-        # admin userId when you use LDAP login
-        admin: read-only-admin
-        identity-attribute: uid
-        email-attribute: mail
+        # admin username when you use LDAP login
+        admin-username: admin_user01
+        admin-user-filter: (&(cn={0})(sn=Bar3))
+        identity-attribute: cn
+        email-attribute: uid
         # action when ldap user is not exist (supported types: CREATE,DENY)
         not-exist-action: CREATE
       ssl:
diff --git 
a/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/resources/docker/ldap-login/docker-compose.yaml
 
b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/resources/docker/ldap-login/docker-compose.yaml
new file mode 100644
index 0000000000..28d91849c1
--- /dev/null
+++ 
b/dolphinscheduler-api-test/dolphinscheduler-api-test-case/src/test/resources/docker/ldap-login/docker-compose.yaml
@@ -0,0 +1,63 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+version: "3.8"
+
+services:
+  dolphinscheduler:
+    image: apache/dolphinscheduler-standalone-server:ci
+    environment:
+      WORKER_TENANT_AUTO_CREATE: 'true'
+    ports:
+      - "12345:12345"
+    volumes:
+      - 
./application.yaml:/opt/dolphinscheduler/standalone-server/conf/application.yaml
+    networks:
+      - api-test
+    healthcheck:
+      test: [ "CMD", "curl", 
"http://localhost:12345/dolphinscheduler/actuator/health"; ]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+    depends_on:
+      - openldap
+  openldap:
+    hostname: openldap
+    image: bitnami/openldap:2.6
+    ports:
+      - '1389:1389'
+      - '1636:1636'
+    environment:
+      - LDAP_ADMIN_USERNAME=admin
+      - LDAP_ADMIN_PASSWORD=adminpassword
+      - LDAP_USERS=admin_user01,general_user02,admin_user03
+      - LDAP_PASSWORDS=123,123,123
+      - LDAP_ROOT=dc=example,dc=org
+      - LDAP_ADMIN_DN=cn=admin,dc=example,dc=org
+    networks:
+      - api-test
+    tty: true
+    stdin_open: true
+    restart: always
+    healthcheck:
+      test: ldapsearch -x -H 'ldap://127.0.0.1:1389' -D 
'cn=admin,dc=example,dc=org' -w adminpassword -b 'ou=users,dc=example,dc=org' 
'(cn=admin_user01)'
+      interval: 5s
+      timeout: 60s
+      retries: 120
+
+networks:
+  api-test:
diff --git a/dolphinscheduler-api-test/pom.xml 
b/dolphinscheduler-api-test/pom.xml
index 095cefd64c..c16c6c6a6b 100644
--- a/dolphinscheduler-api-test/pom.xml
+++ b/dolphinscheduler-api-test/pom.xml
@@ -36,7 +36,8 @@
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 
         <junit.version>5.7.2</junit.version>
-        <selenium.version>3.141.59</selenium.version>
+        <selenium.version>4.21.0</selenium.version>
+        <testcontainers.version>1.19.8</testcontainers.version>
         <lombok.version>1.18.24</lombok.version>
         <assertj-core.version>3.23.1</assertj-core.version>
         <awaitility.version>4.1.0</awaitility.version>
@@ -133,7 +134,7 @@
             <dependency>
                 <groupId>org.testcontainers</groupId>
                 <artifactId>testcontainers-bom</artifactId>
-                <version>1.18.1</version>
+                <version>${testcontainers.version}</version>
                 <scope>import</scope>
                 <type>pom</type>
             </dependency>
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/LdapLoginResult.java
similarity index 67%
copy from 
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java
copy to 
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/LdapLoginResult.java
index a7ae0dd9f1..47c458ac77 100644
--- 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/LdapLoginResult.java
@@ -15,15 +15,21 @@
  * limitations under the License.
  */
 
-package org.apache.dolphinscheduler.api.security.impl.pwd;
+package org.apache.dolphinscheduler.api.dto;
 
-import org.apache.dolphinscheduler.api.security.impl.AbstractAuthenticator;
-import org.apache.dolphinscheduler.dao.entity.User;
+import org.apache.dolphinscheduler.common.enums.UserType;
 
-public class PasswordAuthenticator extends AbstractAuthenticator {
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
 
-    @Override
-    public User login(String userId, String password) {
-        return userService.queryUser(userId, password);
-    }
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class LdapLoginResult {
+
+    private boolean success;
+    private String ldapEmail;
+    private UserType userType;
+    private String userName;
 }
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/AbstractAuthenticator.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/AbstractAuthenticator.java
index 43b7e57402..7b9c3f5a43 100644
--- 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/AbstractAuthenticator.java
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/AbstractAuthenticator.java
@@ -59,16 +59,16 @@ public abstract class AbstractAuthenticator implements 
Authenticator {
     /**
      * user login and return user in db
      *
-     * @param userId user identity field
+     * @param userName user identity field
      * @param password user login password
      * @return user object in databse
      */
-    public abstract User login(@NonNull String userId, String password);
+    public abstract User login(@NonNull String userName, String password);
 
     @Override
-    public Result<Map<String, String>> authenticate(@NonNull String userId, 
String password, @NonNull String ip) {
+    public Result<Map<String, String>> authenticate(@NonNull String userName, 
String password, @NonNull String ip) {
         Result<Map<String, String>> result = new Result<>();
-        User user = login(userId, password);
+        User user = login(userName, password);
         if (user == null) {
             if (Objects.equals(securityConfig.getType(), 
AuthenticationType.CASDOOR_SSO.name())) {
                 log.error("State or code entered incorrectly.");
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticator.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticator.java
index 64f15eeeb2..030bc09fd7 100644
--- 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticator.java
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticator.java
@@ -17,6 +17,7 @@
 
 package org.apache.dolphinscheduler.api.security.impl.ldap;
 
+import org.apache.dolphinscheduler.api.dto.LdapLoginResult;
 import org.apache.dolphinscheduler.api.security.impl.AbstractAuthenticator;
 import org.apache.dolphinscheduler.dao.entity.User;
 
@@ -30,14 +31,14 @@ public class LdapAuthenticator extends 
AbstractAuthenticator {
     LdapService ldapService;
 
     @Override
-    public User login(@NonNull String userId, String password) {
+    public User login(@NonNull String userName, String password) {
         User user = null;
-        String ldapEmail = ldapService.ldapLogin(userId, password);
-        if (ldapEmail != null) {
+        LdapLoginResult ldapLoginResult = ldapService.ldapLogin(userName, 
password);
+        if (ldapLoginResult.isSuccess()) {
             // check if user exist
-            user = userService.getUserByUserName(userId);
+            user = userService.getUserByUserName(userName);
             if (user == null && ldapService.createIfUserNotExists()) {
-                user = userService.createUser(ldapService.getUserType(userId), 
userId, ldapEmail);
+                user = userService.createUser(ldapLoginResult.getUserType(), 
userName, ldapLoginResult.getLdapEmail());
             }
         }
         return user;
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapService.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapService.java
index 058280b81f..3a394809b4 100644
--- 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapService.java
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapService.java
@@ -17,11 +17,13 @@
 
 package org.apache.dolphinscheduler.api.security.impl.ldap;
 
+import org.apache.dolphinscheduler.api.dto.LdapLoginResult;
 import org.apache.dolphinscheduler.api.security.LdapUserNotExistActionType;
 import org.apache.dolphinscheduler.common.enums.UserType;
 
 import org.apache.commons.lang3.StringUtils;
 
+import java.util.Objects;
 import java.util.Properties;
 
 import javax.naming.Context;
@@ -46,11 +48,14 @@ import org.springframework.stereotype.Component;
 @Slf4j
 public class LdapService {
 
-    @Value("${security.authentication.ldap.user.admin:#{null}}")
-    private String adminUserId;
+    @Value("${security.authentication.ldap.user.admin-username:#{null}}")
+    private String ldapAdminUserName;
 
-    @Value("${security.authentication.ldap.urls:#{null}}")
-    private String ldapUrls;
+    @Value("${security.authentication.ldap.user.admin-user-filter:#{null}}")
+    private String ldapAdminUserFilter;
+
+    @Value("${security.authentication.ldap.url:#{null}}")
+    private String ldapUrl;
 
     @Value("${security.authentication.ldap.base-dn:#{null}}")
     private String ldapBaseDn;
@@ -67,7 +72,7 @@ public class LdapService {
     @Value("${security.authentication.ldap.user.email-attribute:#{null}}")
     private String ldapEmailAttribute;
 
-    @Value("${security.authentication.ldap.user.not-exist-action:CREATE}")
+    @Value("${security.authentication.ldap.user.not-exist-action:DENY}")
     private String ldapUserNotExistAction;
 
     @Value("${security.authentication.ldap.ssl.enable:false}")
@@ -79,56 +84,58 @@ public class LdapService {
     @Value("${security.authentication.ldap.ssl.trust-store-password:#{null}}")
     private String trustStorePassword;
 
-    /***
-     * get user type by configured admin userId
-     * @param userId login userId
-     * @return user type
-     */
-    public UserType getUserType(String userId) {
-        return adminUserId.equalsIgnoreCase(userId) ? UserType.ADMIN_USER : 
UserType.GENERAL_USER;
-    }
-
     /**
-     * login by userId and return user email
-     *
-     * @param userId user identity id
-     * @param userPwd user login password
-     * @return user email
+     * login by userName and return LdapLoginResult
      */
-    public String ldapLogin(String userId, String userPwd) {
+    public LdapLoginResult ldapLogin(String userName, String userPwd) {
         Properties searchEnv = getManagerLdapEnv();
         LdapContext ctx = null;
+        LdapLoginResult ldapLoginResult = new LdapLoginResult();
+        ldapLoginResult.setSuccess(false);
+        if (StringUtils.isEmpty(ldapEmailAttribute)) {
+            log.warn("ldap email attribute is empty, skipping ldap 
authentication");
+            return ldapLoginResult;
+        }
+
         try {
             // Connect to the LDAP server and Authenticate with a service user 
of whom we know the DN and credentials
             ctx = new InitialLdapContext(searchEnv, null);
             SearchControls sc = new SearchControls();
             sc.setReturningAttributes(new String[]{ldapEmailAttribute});
             sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
-            EqualsFilter filter = new 
EqualsFilter(ldapUserIdentifyingAttribute, userId);
-            NamingEnumeration<SearchResult> results = ctx.search(ldapBaseDn, 
filter.toString(), sc);
-            if (results.hasMore()) {
-                // get the users DN (distinguishedName) from the result
-                SearchResult result = results.next();
-                NamingEnumeration<? extends Attribute> attrs = 
result.getAttributes().getAll();
-                while (attrs.hasMore()) {
-                    // Open another connection to the LDAP server with the 
found DN and the password
-                    searchEnv.put(Context.SECURITY_PRINCIPAL, 
result.getNameInNamespace());
-                    searchEnv.put(Context.SECURITY_CREDENTIALS, userPwd);
-                    try {
-                        new InitialDirContext(searchEnv);
-                    } catch (Exception e) {
-                        log.warn("invalid ldap credentials or ldap search 
error", e);
-                        return null;
-                    }
-                    Attribute attr = attrs.next();
-                    if (attr.getID().equals(ldapEmailAttribute)) {
-                        return (String) attr.get();
-                    }
+            EqualsFilter userFilter = new 
EqualsFilter(ldapUserIdentifyingAttribute, userName);
+            String userSearchEmail = ldapSearch(ctx, null, userPwd, 
userFilter.toString(), sc, searchEnv);
+
+            if (StringUtils.isNotEmpty(ldapAdminUserFilter)) {
+                String adminFilterSearchEmail = ldapSearch(ctx, userName, 
userPwd, ldapAdminUserFilter, sc, searchEnv);
+                if (adminFilterSearchEmail != null) {
+                    ldapLoginResult.setLdapEmail(adminFilterSearchEmail);
+                    ldapLoginResult.setUserType(UserType.ADMIN_USER);
+                    ldapLoginResult.setUserName(userName);
+                    ldapLoginResult.setSuccess(true);
+                    return ldapLoginResult;
                 }
+            } else {
+                log.debug("ldap admin user filter is empty, skipping admin 
user filter search");
+            }
+
+            if (userSearchEmail != null) {
+                if (Objects.equals(ldapAdminUserName, userName)) {
+                    ldapLoginResult.setUserType(UserType.ADMIN_USER);
+                } else {
+                    ldapLoginResult.setUserType(UserType.GENERAL_USER);
+                }
+
+                ldapLoginResult.setLdapEmail(userSearchEmail);
+                ldapLoginResult.setUserName(userName);
+                ldapLoginResult.setSuccess(true);
+                return ldapLoginResult;
+            } else {
+                log.debug("user email attribute {} not found in ldap", 
ldapEmailAttribute);
             }
         } catch (NamingException e) {
             log.error("ldap search error", e);
-            return null;
+            return ldapLoginResult;
         } finally {
             try {
                 if (ctx != null) {
@@ -139,7 +146,7 @@ public class LdapService {
             }
         }
 
-        return null;
+        return ldapLoginResult;
     }
 
     /***
@@ -152,7 +159,7 @@ public class LdapService {
         env.put(Context.SECURITY_AUTHENTICATION, "simple");
         env.put(Context.SECURITY_PRINCIPAL, ldapSecurityPrincipal);
         env.put(Context.SECURITY_CREDENTIALS, ldapPrincipalPassword);
-        env.put(Context.PROVIDER_URL, ldapUrls);
+        env.put(Context.PROVIDER_URL, ldapUrl);
 
         if (sslEnable) {
             env.put(Context.SECURITY_PROTOCOL, "ssl");
@@ -164,6 +171,42 @@ public class LdapService {
         return env;
     }
 
+    private String ldapSearch(LdapContext ctx,
+                              String userName,
+                              String userPwd,
+                              String filter,
+                              SearchControls sc,
+                              Properties searchEnv) throws NamingException {
+        NamingEnumeration<SearchResult> results;
+        if (userName == null) {
+            results = ctx.search(ldapBaseDn, filter, sc);
+        } else {
+            results = ctx.search(ldapBaseDn, filter, new Object[]{userName}, 
sc);
+        }
+        if (results.hasMore()) {
+            // get the users DN (distinguishedName) from the result
+            SearchResult result = results.next();
+            NamingEnumeration<? extends Attribute> attrs = 
result.getAttributes().getAll();
+            while (attrs.hasMore()) {
+                // Open another connection to the LDAP server with the found 
DN and the password
+                searchEnv.put(Context.SECURITY_PRINCIPAL, 
result.getNameInNamespace());
+                searchEnv.put(Context.SECURITY_CREDENTIALS, userPwd);
+                try {
+                    new InitialDirContext(searchEnv);
+                } catch (Exception e) {
+                    log.warn("invalid ldap credentials or ldap search error", 
e);
+                    return null;
+                }
+                Attribute attr = attrs.next();
+                if (attr.getID().equals(ldapEmailAttribute)) {
+                    return (String) attr.get();
+                }
+            }
+        }
+
+        return null;
+    }
+
     public LdapUserNotExistActionType getLdapUserNotExistAction() {
         if (StringUtils.isBlank(ldapUserNotExistAction)) {
             log.info(
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java
index a7ae0dd9f1..86c419a605 100644
--- 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/pwd/PasswordAuthenticator.java
@@ -23,7 +23,7 @@ import org.apache.dolphinscheduler.dao.entity.User;
 public class PasswordAuthenticator extends AbstractAuthenticator {
 
     @Override
-    public User login(String userId, String password) {
-        return userService.queryUser(userId, password);
+    public User login(String userName, String password) {
+        return userService.queryUser(userName, password);
     }
 }
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/sso/CasdoorAuthenticator.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/sso/CasdoorAuthenticator.java
index 4d8cf93ada..5713696f8e 100644
--- 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/sso/CasdoorAuthenticator.java
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/security/impl/sso/CasdoorAuthenticator.java
@@ -48,7 +48,7 @@ public class CasdoorAuthenticator extends 
AbstractSsoAuthenticator {
     private String adminUserName;
 
     @Override
-    public User login(@NonNull String state, String code) {
+    public User login(@NonNull String userName, String code) {
         ServletRequestAttributes servletRequestAttributes =
                 (ServletRequestAttributes) 
RequestContextHolder.getRequestAttributes();
         if (servletRequestAttributes == null) {
@@ -59,11 +59,11 @@ public class CasdoorAuthenticator extends 
AbstractSsoAuthenticator {
         // Invalid state
         request.getSession().setAttribute(Constants.SSO_LOGIN_USER_STATE, 
null);
         // Check state to protect from CSRF attack
-        if (originalState == null || 
!MessageDigest.isEqual(originalState.getBytes(), state.getBytes())) {
+        if (originalState == null || 
!MessageDigest.isEqual(originalState.getBytes(), userName.getBytes())) {
             return null;
         }
 
-        String token = casdoorAuthService.getOAuthToken(code, state);
+        String token = casdoorAuthService.getOAuthToken(code, userName);
         CasdoorUser casdoorUser = casdoorAuthService.parseJwtToken(token);
         User user = null;
         if (casdoorUser.getName() != null) {
diff --git a/dolphinscheduler-api/src/main/resources/application.yaml 
b/dolphinscheduler-api/src/main/resources/application.yaml
index 9b0e94d644..4578aa08ac 100644
--- a/dolphinscheduler-api/src/main/resources/application.yaml
+++ b/dolphinscheduler-api/src/main/resources/application.yaml
@@ -175,17 +175,19 @@ security:
     # IF you set type `LDAP`, below config will be effective
     ldap:
       # ldap server config
-      urls: ldap://ldap.forumsys.com:389/
+      url: ldap://ldap.forumsys.com:389/
       base-dn: dc=example,dc=com
-      username: cn=read-only-admin,dc=example,dc=com
+      username: cn=admin,dc=example,dc=com
       password: password
       user:
-        # admin userId when you use LDAP login
-        admin: read-only-admin
+        # admin username when you use LDAP login
+        admin-username: ldap-admin
+        # user search filter to find admin user
+        admin-user-filter: (&(cn={0}))
         identity-attribute: uid
         email-attribute: mail
         # action when ldap user is not exist (supported types: CREATE,DENY)
-        not-exist-action: CREATE
+        not-exist-action: DENY
       ssl:
         enable: false
         # jks file absolute path && password
diff --git 
a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java
 
b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java
index 88662273ea..ea09ec5a22 100644
--- 
a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java
+++ 
b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/SecurityConfigLDAPTest.java
@@ -27,6 +27,7 @@ import org.springframework.test.context.TestPropertySource;
 
 @TestPropertySource(properties = {
         "security.authentication.type=LDAP",
+        "security.authentication.ldap.user.not-exist-action=CREATE"
 })
 public class SecurityConfigLDAPTest extends AbstractControllerTest {
 
diff --git 
a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java
 
b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java
index 26f086a907..9e75634bcc 100644
--- 
a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java
+++ 
b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapAuthenticatorTest.java
@@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.when;
 
 import org.apache.dolphinscheduler.api.controller.AbstractControllerTest;
+import org.apache.dolphinscheduler.api.dto.LdapLoginResult;
 import org.apache.dolphinscheduler.api.enums.Status;
 import org.apache.dolphinscheduler.api.security.LdapUserNotExistActionType;
 import org.apache.dolphinscheduler.api.service.SessionService;
@@ -81,11 +82,13 @@ public class LdapAuthenticatorTest extends 
AbstractControllerTest {
     private User mockUser;
     private Session mockSession;
 
-    private String ldapUid = "test";
-    private String ldapUserPwd = "password";
-    private String ldapEmail = "[email protected]";
-    private String ip = "127.0.0.1";
-    private UserType userType = UserType.GENERAL_USER;
+    private final String ldapUid = "test";
+    private final String ldapUserPwd = "password";
+    private final String ldapEmail = "[email protected]";
+    private final String ip = "127.0.0.1";
+    private final UserType userType = UserType.GENERAL_USER;
+    private final LdapLoginResult ldapLoginResultSuccess = new 
LdapLoginResult(true, ldapEmail, userType, ldapUid);
+    private final LdapLoginResult ldapLoginResultFailed = new 
LdapLoginResult(false, ldapEmail, userType, ldapUid);
 
     @Override
     @BeforeEach
@@ -109,7 +112,7 @@ public class LdapAuthenticatorTest extends 
AbstractControllerTest {
 
     @Test
     public void testAuthenticate() {
-        when(ldapService.ldapLogin(ldapUid, 
ldapUserPwd)).thenReturn(ldapEmail);
+        when(ldapService.ldapLogin(ldapUid, 
ldapUserPwd)).thenReturn(ldapLoginResultSuccess);
         
when(sessionService.createSessionIfAbsent(Mockito.any(User.class))).thenReturn(mockSession);
 
         // test username pwd correct and user not exist, config user not exist 
action deny, so login denied
@@ -131,8 +134,9 @@ public class LdapAuthenticatorTest extends 
AbstractControllerTest {
         Assertions.assertEquals(Status.LOGIN_SESSION_FAILED.getCode(), (int) 
result.getCode());
 
         // test username pwd error, login failed
-        when(ldapService.ldapLogin(ldapUid, ldapUserPwd)).thenReturn(null);
-        result = ldapAuthenticator.authenticate(ldapUid, ldapUserPwd, ip);
+        
when(sessionService.createSessionIfAbsent(Mockito.any(User.class))).thenReturn(mockSession);
+        when(ldapService.ldapLogin(ldapUid, 
"123")).thenReturn(ldapLoginResultFailed);
+        result = ldapAuthenticator.authenticate(ldapUid, "123", ip);
         Assertions.assertEquals(Status.USER_NAME_PASSWD_ERROR.getCode(), (int) 
result.getCode());
     }
 
diff --git 
a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java
 
b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java
deleted file mode 100644
index 30dbd80479..0000000000
--- 
a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/security/impl/ldap/LdapServiceTest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.dolphinscheduler.api.security.impl.ldap;
-
-import org.apache.dolphinscheduler.api.ApiApplicationServer;
-import org.apache.dolphinscheduler.common.enums.ProfileType;
-import org.apache.dolphinscheduler.common.enums.UserType;
-
-import java.lang.reflect.Field;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.ActiveProfiles;
-import org.springframework.test.context.TestPropertySource;
-
-@Disabled
-@ActiveProfiles(ProfileType.H2)
-@SpringBootTest(classes = ApiApplicationServer.class)
-@TestPropertySource(properties = {
-        "security.authentication.type=LDAP",
-        "security.authentication.ldap.user.admin=read-only-admin",
-        "security.authentication.ldap.urls=ldap://ldap.forumsys.com:389/";,
-        "security.authentication.ldap.base-dn=dc=example,dc=com",
-        
"security.authentication.ldap.username=cn=read-only-admin,dc=example,dc=com",
-        "security.authentication.ldap.password=password",
-        "security.authentication.ldap.user.identity-attribute=uid",
-        "security.authentication.ldap.user.email-attribute=mail",
-        "security.authentication.ldap.user.not-exist-action=CREATE",
-        "security.authentication.ldap.ssl.enable=false",
-        "security.authentication.ldap.ssl.trust-store=",
-        "security.authentication.ldap.ssl.trust-store-password=",
-})
-public class LdapServiceTest {
-
-    @Autowired
-    protected AutowireCapableBeanFactory beanFactory;
-
-    private LdapService ldapService;
-
-    private final String username = "tesla";
-    private final String correctPassword = "password";
-
-    @BeforeEach
-    public void setUp() {
-        ldapService = new LdapService();
-        beanFactory.autowireBean(ldapService);
-    }
-
-    @Test
-    public void getUserType() {
-        UserType userType = ldapService.getUserType("read-only-admin");
-        Assertions.assertEquals(UserType.ADMIN_USER, userType);
-    }
-
-    @Test
-    public void ldapLogin() throws NoSuchFieldException, 
IllegalAccessException {
-        changeSslEnable(false);
-        String email = ldapService.ldapLogin(username, correctPassword);
-        Assertions.assertEquals("[email protected]", email);
-    }
-
-    @Test
-    public void ldapLoginError() throws NoSuchFieldException, 
IllegalAccessException {
-        changeSslEnable(false);
-        String email2 = ldapService.ldapLogin(username, "error password");
-        Assertions.assertNull(email2);
-    }
-
-    @Test
-    public void ldapLoginSSL() throws NoSuchFieldException, 
IllegalAccessException {
-        changeSslEnable(true);
-        String email = ldapService.ldapLogin(username, correctPassword);
-        Assertions.assertNull(email);
-    }
-
-    private void changeSslEnable(boolean sslEnable) throws 
NoSuchFieldException, IllegalAccessException {
-        Class<LdapService> ldapServiceClass = LdapService.class;
-        Field sslEnableField = ldapServiceClass.getDeclaredField("sslEnable");
-        sslEnableField.setAccessible(true);
-        sslEnableField.set(ldapService, sslEnable);
-        if (sslEnable) {
-            Field trustStorePasswordField = 
ldapServiceClass.getDeclaredField("trustStorePassword");
-            trustStorePasswordField.setAccessible(true);
-            trustStorePasswordField.set(ldapService, "trustStorePassword");
-        }
-    }
-}
diff --git a/dolphinscheduler-api/src/test/resources/application.yaml 
b/dolphinscheduler-api/src/test/resources/application.yaml
index 5eb7e1f8d7..b5c3373d65 100644
--- a/dolphinscheduler-api/src/test/resources/application.yaml
+++ b/dolphinscheduler-api/src/test/resources/application.yaml
@@ -100,17 +100,18 @@ security:
     # IF you set type `LDAP`, below config will be effective
     ldap:
       # ldap server config
-      urls: ldap://ldap.forumsys.com:389/
+      url: ldap://ldap.forumsys.com:389/
       base-dn: dc=example,dc=com
       username: cn=read-only-admin,dc=example,dc=com
       password: password
       user:
-        # admin userId when you use LDAP login
-        admin: read-only-admin
+        # admin username when you use LDAP login
+        admin-username: admin
+        admin-user-filter: (&(cn={0}))
         identity-attribute: uid
         email-attribute: mail
         # action when ldap user is not exist (supported types: CREATE,DENY)
-        not-exist-action: CREATE
+        not-exist-action: DENY
       ssl:
         enable: false
         # jks file absolute path && password
diff --git 
a/dolphinscheduler-standalone-server/src/main/resources/application.yaml 
b/dolphinscheduler-standalone-server/src/main/resources/application.yaml
index 97b9b6d22d..5f83729bad 100644
--- a/dolphinscheduler-standalone-server/src/main/resources/application.yaml
+++ b/dolphinscheduler-standalone-server/src/main/resources/application.yaml
@@ -90,17 +90,19 @@ security:
     # IF you set type `LDAP`, below config will be effective
     ldap:
       # ldap server config
-      urls: ldap://ldap.forumsys.com:389/
+      url: ldap://ldap.forumsys.com:389/
       base-dn: dc=example,dc=com
-      username: cn=read-only-admin,dc=example,dc=com
+      username: admin,dc=example,dc=com
       password: password
       user:
-        # admin userId when you use LDAP login
-        admin: read-only-admin
+        # admin username when you use LDAP login
+        admin-username: ldap-admin
+        # user search filter to find admin user
+        admin-user-filter: (&(cn={0}))
         identity-attribute: uid
         email-attribute: mail
         # action when ldap user is not exist (supported types: CREATE,DENY)
-        not-exist-action: CREATE
+        not-exist-action: DENY
       ssl:
         enable: false
         # jks file absolute path && password

Reply via email to