diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthEntryPoint.java b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthEntryPoint.java
index f67da75ee9..8431b6f080 100644
--- a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthEntryPoint.java
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthEntryPoint.java
@@ -2,7 +2,7 @@
* @Author: jackning 270580156@qq.com
* @Date: 2024-01-29 12:45:01
* @LastEditors: jackning 270580156@qq.com
- * @LastEditTime: 2024-11-12 14:32:01
+ * @LastEditTime: 2025-03-10 12:24:39
* @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
* Please be aware of the BSL license restrictions before installing Bytedesk IM –
* selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/ldap/LdapSecurityConfig.java b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/ldap/LdapSecurityConfig.java
new file mode 100644
index 0000000000..7e7a3148be
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/ldap/LdapSecurityConfig.java
@@ -0,0 +1,72 @@
+/*
+ * @Author: jackning 270580156@qq.com
+ * @Date: 2025-03-10 12:25:11
+ * @LastEditors: jackning 270580156@qq.com
+ * @LastEditTime: 2025-03-10 12:38:51
+ * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk
+ * Please be aware of the BSL license restrictions before installing Bytedesk IM –
+ * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license.
+ * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE
+ * contact: 270580156@qq.com
+ *
+ * Copyright (c) 2025 by bytedesk.com, All Rights Reserved.
+ */
+package com.bytedesk.core.rbac.auth.ldap;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.ldap.core.LdapTemplate;
+import org.springframework.ldap.core.support.LdapContextSource;
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.authentication.configuration.GlobalAuthenticationConfigurerAdapter;
+import org.springframework.security.ldap.authentication.BindAuthenticator;
+import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
+import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
+import org.springframework.security.ldap.userdetails.LdapUserDetailsMapper;
+
+@Configuration
+public class LdapSecurityConfig extends GlobalAuthenticationConfigurerAdapter {
+
+ @Override
+ public void init(AuthenticationManagerBuilder auth) throws Exception {
+ auth.authenticationProvider(ldapAuthenticationProvider());
+ }
+
+ @Bean
+ public AuthenticationProvider ldapAuthenticationProvider() {
+ LdapAuthenticationProvider provider = new LdapAuthenticationProvider(bindAuthenticator());
+ provider.setUserDetailsContextMapper(new LdapUserDetailsMapper());
+ return provider;
+ }
+
+ @Bean
+ public BindAuthenticator bindAuthenticator() {
+ BindAuthenticator authenticator = new BindAuthenticator(contextSource());
+ authenticator.setUserSearch(userSearch());
+ return authenticator;
+ }
+
+ @Bean
+ public FilterBasedLdapUserSearch userSearch() {
+ return new FilterBasedLdapUserSearch(
+ "${spring.ldap.base}", // 搜索基础
+ "(uid={0})", // 用户搜索过滤器
+ contextSource());
+ }
+
+ @Bean
+ public LdapContextSource contextSource() {
+ LdapContextSource contextSource = new LdapContextSource();
+ contextSource.setUrl("${spring.ldap.urls}");
+ contextSource.setBase("${spring.ldap.base}");
+ contextSource.setUserDn("${spring.ldap.username}");
+ contextSource.setPassword("${spring.ldap.password}");
+ return contextSource;
+ }
+
+ @Bean
+ public LdapTemplate ldapTemplate() {
+ return new LdapTemplate(contextSource());
+ }
+}
\ No newline at end of file
diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/ldap/LdapUserService.java b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/ldap/LdapUserService.java
new file mode 100644
index 0000000000..82fa5e658a
--- /dev/null
+++ b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/ldap/LdapUserService.java
@@ -0,0 +1,19 @@
+package com.bytedesk.core.rbac.auth.ldap;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.ldap.core.LdapTemplate;
+import org.springframework.ldap.filter.EqualsFilter;
+import org.springframework.ldap.filter.Filter;
+import org.springframework.stereotype.Service;
+
+@Service
+public class LdapUserService {
+
+ @Autowired
+ private LdapTemplate ldapTemplate;
+
+ public boolean authenticate(String username, String password) {
+ Filter filter = new EqualsFilter("uid", username);
+ return ldapTemplate.authenticate("", filter.encode(), password);
+ }
+}
\ No newline at end of file
diff --git a/modules/pom.xml b/modules/pom.xml
index 7e3862ffd5..12e4c52f36 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -135,6 +135,24 @@
provided
+
+
+ org.springframework.security
+ spring-security-ldap
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-ldap
+ provided
+
+
+
+ com.unboundid
+ unboundid-ldapsdk
+ test
+
+
@@ -411,6 +429,7 @@
provided
+
diff --git a/starter/compose.yaml b/starter/compose.yaml
deleted file mode 100644
index 916fc2b794..0000000000
--- a/starter/compose.yaml
+++ /dev/null
@@ -1,82 +0,0 @@
-services:
- bytedesk-mysql:
- image: mysql:latest
- container_name: mysql-bytedesk
- environment:
- MYSQL_DATABASE: bytedesk
- MYSQL_ROOT_PASSWORD: r8FqfdbWUaN3
- ports:
- - "3306:3306"
- volumes:
- - mysql_data:/var/lib/mysql
- networks:
- - bytedesk-network
-
- bytedesk-redis:
- image: redis/redis-stack-server:latest
- container_name: redis-bytedesk
- ports:
- - "6379:6379"
- environment:
- - REDIS_ARGS=--requirepass qfRxz3tVT8Nh
- volumes:
- - redis_data:/data
- networks:
- - bytedesk-network
-
- bytedesk-ollama:
- image: ollama/ollama:latest
- container_name: ollama-bytedesk
- ports:
- - "11434:11434"
- volumes:
- - ollama_data:/root/.ollama
- environment:
- - OLLAMA_MODELS=deepseek-r1:1.5b
- command: serve
- networks:
- - bytedesk-network
-
- bytedesk-prometheus:
- image: prom/prometheus:latest
- container_name: prometheus-bytedesk
- ports:
- - "9090:9090"
- command:
- - '--config.file=/etc/prometheus/prometheus.yml'
- - '--storage.tsdb.path=/prometheus'
- - '--web.enable-lifecycle'
- - '--web.console.libraries=/usr/share/prometheus/console_libraries'
- - '--web.console.templates=/usr/share/prometheus/consoles'
- - '--storage.tsdb.retention.time=15d'
- - '--web.enable-admin-api'
- - '--web.external-url=http://localhost:9090'
- volumes:
- - prometheus_data:/prometheus
- - ./prometheus.yml:/etc/prometheus/prometheus.yml
- networks:
- - bytedesk-network
-
- bytedesk-grafana:
- image: grafana/grafana:latest
- container_name: grafana-bytedesk
- ports:
- - "3000:3000"
- environment:
- - GF_SECURITY_ADMIN_USER=admin
- - GF_SECURITY_ADMIN_PASSWORD=admin
- volumes:
- - grafana_data:/var/lib/grafana
- networks:
- - bytedesk-network
-
-volumes:
- mysql_data:
- redis_data:
- ollama_data:
- prometheus_data:
- grafana_data:
-
-networks:
- bytedesk-network:
- driver: bridge
diff --git a/starter/src/main/resources/application-dev.properties b/starter/src/main/resources/application-dev.properties
index d98cf3bca2..715170d103 100644
--- a/starter/src/main/resources/application-dev.properties
+++ b/starter/src/main/resources/application-dev.properties
@@ -143,6 +143,22 @@ bytedesk.redis.pool-config.maxIdle=64
bytedesk.redis.pool-config.maxTotal=64
bytedesk.redis.pool-config.minIdle=8
+# ===============================
+# LDAP Configuration
+# ===============================
+# LDAP 服务器地址
+spring.ldap.urls=ldap://127.0.0.1:389
+# LDAP 基础目录
+spring.ldap.base=dc=example,dc=com
+# LDAP 管理员用户名
+spring.ldap.username=cn=admin,dc=example,dc=com
+# LDAP 管理员密码
+spring.ldap.password=admin
+# LDAP 是否只读
+spring.ldap.anonymous-read-only=false
+# LDAP 是否启用匿名访问
+spring.ldap.anonymous-enabled=true
+
# ===============================
#=logging
# https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#appendix.application-properties.core
diff --git a/starter/src/test/java/com/bytedesk/auth/ldap/LdapAuthenticationTest.java b/starter/src/test/java/com/bytedesk/auth/ldap/LdapAuthenticationTest.java
new file mode 100644
index 0000000000..ef767933b6
--- /dev/null
+++ b/starter/src/test/java/com/bytedesk/auth/ldap/LdapAuthenticationTest.java
@@ -0,0 +1,33 @@
+package com.bytedesk.auth.ldap;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+
+import com.bytedesk.core.rbac.auth.ldap.LdapUserService;
+
+@SpringBootTest
+@ActiveProfiles("test")
+public class LdapAuthenticationTest {
+
+ @Autowired
+ private LdapUserService ldapUserService;
+
+ @Test
+ public void testAuthentication() {
+ // 测试正确的用户名和密码
+ assertTrue(ldapUserService.authenticate("admin", "admin123"));
+ assertTrue(ldapUserService.authenticate("test", "test123"));
+
+ // 测试错误的密码
+ assertFalse(ldapUserService.authenticate("admin", "wrongpassword"));
+ assertFalse(ldapUserService.authenticate("test", "wrongpassword"));
+
+ // 测试不存在的用户
+ assertFalse(ldapUserService.authenticate("nonexistent", "password"));
+ }
+}
\ No newline at end of file
diff --git a/starter/src/test/resources/application-test.properties b/starter/src/test/resources/application-test.properties
new file mode 100644
index 0000000000..9ca7d44856
--- /dev/null
+++ b/starter/src/test/resources/application-test.properties
@@ -0,0 +1,11 @@
+# 嵌入式LDAP服务器配置
+spring.ldap.embedded.base-dn=dc=bytedesk,dc=com
+spring.ldap.embedded.port=8389
+spring.ldap.embedded.ldif=classpath:test-server.ldif
+spring.ldap.embedded.validation.enabled=false
+
+# LDAP客户端配置
+spring.ldap.urls=ldap://localhost:8389
+spring.ldap.base=dc=bytedesk,dc=com
+spring.ldap.username=uid=admin,ou=people,dc=bytedesk,dc=com
+spring.ldap.password=admin123
\ No newline at end of file
diff --git a/starter/src/test/resources/test-server.ldif b/starter/src/test/resources/test-server.ldif
new file mode 100644
index 0000000000..89669e8804
--- /dev/null
+++ b/starter/src/test/resources/test-server.ldif
@@ -0,0 +1,30 @@
+dn: dc=bytedesk,dc=com
+objectclass: top
+objectclass: domain
+objectclass: extensibleObject
+dc: bytedesk
+
+dn: ou=people,dc=bytedesk,dc=com
+objectclass: top
+objectclass: organizationalUnit
+ou: people
+
+dn: uid=admin,ou=people,dc=bytedesk,dc=com
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Admin
+sn: Admin
+uid: admin
+userPassword: admin123
+
+dn: uid=test,ou=people,dc=bytedesk,dc=com
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+cn: Test User
+sn: User
+uid: test
+userPassword: test123
\ No newline at end of file