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

ruanwenjun 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 3b1bb60927 [Improvement-18652][API] Make login session timeout 
configurable (#18653)
3b1bb60927 is described below

commit 3b1bb60927a5f582553fc8860313ca75bd7531de
Author: huangrunxing <[email protected]>
AuthorDate: Tue Sep 22 11:58:02 2026 +0800

    [Improvement-18652][API] Make login session timeout configurable (#18653)
---
 docs/docs/en/architecture/configuration.md           |  1 +
 docs/docs/zh/architecture/configuration.md           |  1 +
 .../api/configuration/ApiConfig.java                 | 10 ++++++++++
 .../api/service/impl/SessionServiceImpl.java         |  8 ++++++--
 .../src/main/resources/application.yaml              |  3 +++
 .../api/controller/LoginControllerTest.java          |  5 ++++-
 .../api/service/SessionServiceTest.java              | 20 ++++++++++++++++++++
 .../dolphinscheduler/common/constants/Constants.java |  2 --
 .../src/main/resources/application.yaml              |  3 +++
 9 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/docs/docs/en/architecture/configuration.md 
b/docs/docs/en/architecture/configuration.md
index 00b98c7356..cb37799a85 100644
--- a/docs/docs/en/architecture/configuration.md
+++ b/docs/docs/en/architecture/configuration.md
@@ -260,6 +260,7 @@ Location: `api-server/conf/application.yaml`
 | casdoor.organization-name                             |                      
                | organization name in Casdoor                                  
                                 |
 | casdoor.application-name                              |                      
                | application name in Casdoor                                   
                                 |
 | casdoor.redirect-url                                  |                      
                | doplhinscheduler login url                                    
                                 |
+| api.session-timeout                                   | 2h                   
                | login session lifetime measured from login time; accepts a 
Duration (e.g. 30m, 12h, 1d)        |
 | api.traffic.control.global.switch                     | false                
                | traffic control global switch                                 
                                 |
 | api.traffic.control.max-global-qps-rate               | 300                  
                | global max request number per second                          
                                 |
 | api.traffic.control.tenant-switch                     | false                
                | traffic control tenant switch                                 
                                 |
diff --git a/docs/docs/zh/architecture/configuration.md 
b/docs/docs/zh/architecture/configuration.md
index 335a9b1d2d..a2b9437955 100644
--- a/docs/docs/zh/architecture/configuration.md
+++ b/docs/docs/zh/architecture/configuration.md
@@ -260,6 +260,7 @@ common.properties配置文件目前主要是配置hadoop/s3/yarn/applicationId
 | casdoor.organization-name                             |                      
                | Casdoor中的组织名称                                   |
 | casdoor.application-name                              |                      
                | Casdoor中的应用名称                                   |
 | casdoor.redirect-url                                  |                      
                | dolphinscheduler登录URL                           |
+| api.session-timeout                                   | 2h                   
                | 登录会话有效期,从登录时刻开始计算,支持 Duration 格式(如 30m、12h、1d)  |
 | api.traffic.control.global.switch                     | false                
                | 流量控制全局开关                                        |
 | api.traffic.control.max-global-qps-rate               | 300                  
                | 全局最大请求数/秒                                       |
 | api.traffic.control.tenant-switch                     | false                
                | 流量控制租户开关                                        |
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/configuration/ApiConfig.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/configuration/ApiConfig.java
index 2ba09ee37b..ef5c49929f 100644
--- 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/configuration/ApiConfig.java
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/configuration/ApiConfig.java
@@ -19,6 +19,7 @@ package org.apache.dolphinscheduler.api.configuration;
 
 import org.apache.commons.lang3.StringUtils;
 
+import java.time.Duration;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -44,6 +45,7 @@ public class ApiConfig implements Validator {
     private String baseUrl;
     private String uiUrl;
     private boolean auditEnable = false;
+    private Duration sessionTimeout = Duration.ofHours(2);
 
     private TrafficConfiguration trafficControl = new TrafficConfiguration();
 
@@ -57,6 +59,7 @@ public class ApiConfig implements Validator {
     @Override
     public void validate(Object target, Errors errors) {
         validatePythonGateway(errors);
+        validateSessionTimeout(errors);
         printConfig();
     }
 
@@ -66,10 +69,17 @@ public class ApiConfig implements Validator {
         }
     }
 
+    private void validateSessionTimeout(Errors errors) {
+        if (sessionTimeout.isZero() || sessionTimeout.isNegative()) {
+            errors.rejectValue("sessionTimeout", null, "should be positive");
+        }
+    }
+
     private void printConfig() {
         log.info("API config: baseUrl -> {} ", baseUrl);
         log.info("API config: uiUrl -> {} ", uiUrl);
         log.info("API config: auditEnable -> {} ", auditEnable);
+        log.info("API config: sessionTimeout -> {} ", sessionTimeout);
         log.info("API config: trafficControl -> {} ", trafficControl);
         log.info("API config: pythonGateway -> {} ", pythonGateway);
     }
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SessionServiceImpl.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SessionServiceImpl.java
index a3571eb19e..b476fd1db6 100644
--- 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SessionServiceImpl.java
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/SessionServiceImpl.java
@@ -17,8 +17,8 @@
 
 package org.apache.dolphinscheduler.api.service.impl;
 
+import org.apache.dolphinscheduler.api.configuration.ApiConfig;
 import org.apache.dolphinscheduler.api.service.SessionService;
-import org.apache.dolphinscheduler.common.constants.Constants;
 import org.apache.dolphinscheduler.dao.entity.Session;
 import org.apache.dolphinscheduler.dao.entity.User;
 import org.apache.dolphinscheduler.dao.repository.SessionDao;
@@ -46,6 +46,9 @@ public class SessionServiceImpl extends BaseServiceImpl 
implements SessionServic
     @Autowired
     private SessionDao sessionDao;
 
+    @Autowired
+    private ApiConfig apiConfig;
+
     @Override
     public Session getSession(String sessionId) {
         if (StringUtils.isBlank(sessionId)) {
@@ -94,7 +97,8 @@ public class SessionServiceImpl extends BaseServiceImpl 
implements SessionServic
 
     @Override
     public boolean isSessionExpire(Session session) {
-        return System.currentTimeMillis() - 
session.getLastLoginTime().getTime() >= Constants.SESSION_TIME_OUT * 1000;
+        return System.currentTimeMillis() - 
session.getLastLoginTime().getTime() >= apiConfig.getSessionTimeout()
+                .toMillis();
     }
 
 }
diff --git a/dolphinscheduler-api/src/main/resources/application.yaml 
b/dolphinscheduler-api/src/main/resources/application.yaml
index 9d3bb1c6a5..58f9017f8b 100644
--- a/dolphinscheduler-api/src/main/resources/application.yaml
+++ b/dolphinscheduler-api/src/main/resources/application.yaml
@@ -142,6 +142,9 @@ api:
   base-url: http://127.0.0.1:12345/dolphinscheduler
   ui-url: http://127.0.0.1:5173
   audit-enable: false
+  # The lifetime of a login session, measured from the moment the user logs in.
+  # Accepts a Duration, e.g. 30m, 12h, 1d. Defaults to 2h when unset.
+  session-timeout: 2h
   # Traffic control, if you turn on this config, the maximum number of 
request/s will be limited.
   # global max request number per second
   # default tenant-level max request number
diff --git 
a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/LoginControllerTest.java
 
b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/LoginControllerTest.java
index 57fb1076df..5f07208400 100644
--- 
a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/LoginControllerTest.java
+++ 
b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/LoginControllerTest.java
@@ -82,6 +82,9 @@ public class LoginControllerTest extends 
AbstractControllerTest {
     @Autowired
     private SessionDao sessionDao;
 
+    @Autowired
+    private ApiConfig apiConfig;
+
     @Test
     public void testLogin() throws Exception {
         MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
@@ -143,7 +146,7 @@ public class LoginControllerTest extends 
AbstractControllerTest {
     @Test
     void testSignOutWithExpireSession() throws Exception {
         final Session session = sessionDao.queryById(sessionId);
-        session.setLastLoginTime(new Date(System.currentTimeMillis() - 
Constants.SESSION_TIME_OUT * 1000 - 1));
+        session.setLastLoginTime(new Date(System.currentTimeMillis() - 
apiConfig.getSessionTimeout().toMillis() - 1));
         sessionDao.updateById(session);
 
         mockMvc.perform(post("/signOut")
diff --git 
a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/SessionServiceTest.java
 
b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/SessionServiceTest.java
index 6023e218dd..6599003069 100644
--- 
a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/SessionServiceTest.java
+++ 
b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/SessionServiceTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.dolphinscheduler.api.service;
 
+import org.apache.dolphinscheduler.api.configuration.ApiConfig;
 import org.apache.dolphinscheduler.api.service.impl.SessionServiceImpl;
 import org.apache.dolphinscheduler.common.enums.UserType;
 import org.apache.dolphinscheduler.common.utils.DateUtils;
@@ -24,6 +25,7 @@ import org.apache.dolphinscheduler.dao.entity.Session;
 import org.apache.dolphinscheduler.dao.entity.User;
 import org.apache.dolphinscheduler.dao.repository.SessionDao;
 
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Date;
@@ -37,6 +39,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Mockito;
+import org.mockito.Spy;
 import org.mockito.junit.jupiter.MockitoExtension;
 
 @ExtendWith(MockitoExtension.class)
@@ -48,10 +51,14 @@ public class SessionServiceTest {
     @Mock
     private SessionDao sessionDao;
 
+    @Spy
+    private ApiConfig apiConfig = new ApiConfig();
+
     private String sessionId = "aaaaaaaaaaaaaaaaaa";
 
     @BeforeEach
     public void setUp() {
+        apiConfig.setSessionTimeout(Duration.ofHours(2));
     }
 
     @AfterEach
@@ -100,6 +107,19 @@ public class SessionServiceTest {
 
     }
 
+    @Test
+    public void testIsSessionExpireUsesConfiguredTimeout() {
+        apiConfig.setSessionTimeout(Duration.ofHours(1));
+
+        Session stillAlive = getSession();
+        stillAlive.setLastLoginTime(new Date(System.currentTimeMillis() - 
Duration.ofMinutes(30).toMillis()));
+        Assertions.assertFalse(sessionService.isSessionExpire(stillAlive));
+
+        Session expired = getSession();
+        expired.setLastLoginTime(new Date(System.currentTimeMillis() - 
Duration.ofMinutes(90).toMillis()));
+        Assertions.assertTrue(sessionService.isSessionExpire(expired));
+    }
+
     private Session getSession() {
         Session session = new Session();
         session.setId(sessionId);
diff --git 
a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/constants/Constants.java
 
b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/constants/Constants.java
index 499ed0cd5c..81783ed285 100644
--- 
a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/constants/Constants.java
+++ 
b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/constants/Constants.java
@@ -248,8 +248,6 @@ public final class Constants {
      */
     public static final String LOCALE_LANGUAGE = "language";
 
-    public static final int SESSION_TIME_OUT = 7200;
-
     public static final int AUTHORIZE_WRITABLE_PERM = 7;
 
     public static final String START_TIME = "start time";
diff --git 
a/dolphinscheduler-standalone-server/src/main/resources/application.yaml 
b/dolphinscheduler-standalone-server/src/main/resources/application.yaml
index bd13f06321..74bafeffbd 100644
--- a/dolphinscheduler-standalone-server/src/main/resources/application.yaml
+++ b/dolphinscheduler-standalone-server/src/main/resources/application.yaml
@@ -260,6 +260,9 @@ alert:
 
 api:
   audit-enable: false
+  # The lifetime of a login session, measured from the moment the user logs in.
+  # Accepts a Duration, e.g. 30m, 12h, 1d. Defaults to 2h when unset.
+  session-timeout: 2h
   # Traffic control, if you turn on this config, the maximum number of 
request/s will be limited.
   # global max request number per second
   # default tenant-level max request number

Reply via email to