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

Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new c73cbea2bf fix: add pre-check on expireTime in AccessTokenManager 
(#6981)
c73cbea2bf is described below

commit c73cbea2bfa1c3da284b861fec82af2a71f3c300
Author: hengyuss <[email protected]>
AuthorDate: Fri Sep 4 09:53:00 2026 +0800

    fix: add pre-check on expireTime in AccessTokenManager (#6981)
    
    * fix: add pre-check on expireTime in AccessTokenManager
    
    * fix: handle malformed access token responses
    
    ---------
    
    Co-authored-by: aias00 <[email protected]>
---
 .../shenyu/sync/data/http/AccessTokenManager.java  | 30 ++++++--
 .../sync/data/http/AccessTokenManagerTest.java     | 80 ++++++++++++++++++++++
 2 files changed, 106 insertions(+), 4 deletions(-)

diff --git 
a/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/AccessTokenManager.java
 
b/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/AccessTokenManager.java
index cd762347ce..6aaf7e2e28 100644
--- 
a/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/AccessTokenManager.java
+++ 
b/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/AccessTokenManager.java
@@ -40,6 +40,7 @@ import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
@@ -132,15 +133,30 @@ public class AccessTokenManager {
             Assert.notNull(responseBody, "Resolve response body failed.");
             String result = responseBody.string();
             Map<String, Object> resultMap = 
GsonUtils.getInstance().convertToMap(result);
-            if 
(!String.valueOf(CommonErrorCode.SUCCESSFUL).equals(String.valueOf(resultMap.get(Constants.ADMIN_RESULT_CODE))))
 {
+            if (Objects.isNull(resultMap)
+                    || 
!String.valueOf(CommonErrorCode.SUCCESSFUL).equals(String.valueOf(resultMap.get(Constants.ADMIN_RESULT_CODE))))
 {
                 LOG.warn("get token from server : [{}] error", server);
                 return false;
             }
             String tokenJson = 
GsonUtils.getInstance().toJson(resultMap.get(Constants.ADMIN_RESULT_DATA));
             LOG.info("login success: {} ", tokenJson);
             Map<String, Object> tokenMap = 
GsonUtils.getInstance().convertToMap(tokenJson);
-            this.accessToken = (String) 
tokenMap.get(Constants.ADMIN_RESULT_TOKEN);
-            this.tokenExpiredTime = (long) 
tokenMap.get(Constants.ADMIN_RESULT_EXPIRED_TIME);
+            if (Objects.isNull(tokenMap)) {
+                LOG.warn("get token from server : [{}] returned null data", 
server);
+                return false;
+            }
+            Object token = tokenMap.get(Constants.ADMIN_RESULT_TOKEN);
+            Object expiredTime = 
tokenMap.get(Constants.ADMIN_RESULT_EXPIRED_TIME);
+            if (!(token instanceof String) || StringUtils.isBlank((String) 
token)) {
+                LOG.warn("get token from server : [{}] missing/invalid token", 
server);
+                return false;
+            }
+            if (!(expiredTime instanceof Number)) {
+                LOG.warn("get token from server : [{}] missing/invalid expired 
time", server);
+                return false;
+            }
+            this.accessToken = (String) token;
+            this.tokenExpiredTime = ((Number) expiredTime).longValue();
             this.tokenRefreshWindow = this.tokenExpiredTime / 10;
             return true;
         } catch (IOException e) {
@@ -151,7 +167,13 @@ public class AccessTokenManager {
 
     private void start(final List<String> servers) {
         this.login(servers);
-        this.executorService.scheduleWithFixedDelay(() -> this.login(servers), 
5000, 5000, TimeUnit.MILLISECONDS);
+        this.executorService.scheduleWithFixedDelay(() -> {
+            try {
+                this.login(servers);
+            } catch (Exception e) {
+                LOG.error("refresh access token error", e);
+            }
+        }, 5000, 5000, TimeUnit.MILLISECONDS);
     }
 
     /**
diff --git 
a/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/AccessTokenManagerTest.java
 
b/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/AccessTokenManagerTest.java
index 98c0379171..61f3a66243 100644
--- 
a/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/AccessTokenManagerTest.java
+++ 
b/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/AccessTokenManagerTest.java
@@ -246,6 +246,86 @@ public class AccessTokenManagerTest {
         assertNull(testManager.getAccessToken());
     }
 
+    @Test
+    public void testDoLoginFailureWhenExpiredTimeMissing() throws Exception {
+        HttpConfig testConfig = new HttpConfig();
+        testConfig.setUrl("http://localhost:8080";);
+        testConfig.setUsername("admin");
+        testConfig.setPassword("password");
+
+        Map<String, Object> tokenData = new HashMap<>();
+        tokenData.put("token", "token");
+        Map<String, Object> responseMap = new HashMap<>();
+        responseMap.put("data", tokenData);
+        responseMap.put("code", CommonErrorCode.SUCCESSFUL);
+
+        
when(mockOkHttpClient.newCall(any(Request.class))).thenReturn(mockCall);
+        when(mockCall.execute()).thenReturn(mockResponse);
+        when(mockResponse.isSuccessful()).thenReturn(true);
+        when(mockResponse.body()).thenReturn(mockResponseBody);
+        
when(mockResponseBody.string()).thenReturn(GsonUtils.getInstance().toJson(responseMap));
+
+        AccessTokenManager testManager = 
createTestAccessTokenManager(mockOkHttpClient, testConfig);
+        Method doLoginMethod = 
AccessTokenManager.class.getDeclaredMethod("doLogin", String.class);
+        doLoginMethod.setAccessible(true);
+
+        assertFalse((Boolean) doLoginMethod.invoke(testManager, 
"http://localhost:8080";));
+        assertNull(testManager.getAccessToken());
+    }
+
+    @Test
+    public void testDoLoginFailureWhenDataNull() throws Exception {
+        HttpConfig testConfig = new HttpConfig();
+        testConfig.setUrl("http://localhost:8080";);
+        testConfig.setUsername("admin");
+        testConfig.setPassword("password");
+
+        Map<String, Object> responseMap = new HashMap<>();
+        responseMap.put("data", null);
+        responseMap.put("code", CommonErrorCode.SUCCESSFUL);
+
+        
when(mockOkHttpClient.newCall(any(Request.class))).thenReturn(mockCall);
+        when(mockCall.execute()).thenReturn(mockResponse);
+        when(mockResponse.isSuccessful()).thenReturn(true);
+        when(mockResponse.body()).thenReturn(mockResponseBody);
+        
when(mockResponseBody.string()).thenReturn(GsonUtils.getInstance().toJson(responseMap));
+
+        AccessTokenManager testManager = 
createTestAccessTokenManager(mockOkHttpClient, testConfig);
+        Method doLoginMethod = 
AccessTokenManager.class.getDeclaredMethod("doLogin", String.class);
+        doLoginMethod.setAccessible(true);
+
+        assertFalse((Boolean) doLoginMethod.invoke(testManager, 
"http://localhost:8080";));
+        assertNull(testManager.getAccessToken());
+    }
+
+    @Test
+    public void testDoLoginFailureWhenExpiredTimeIsString() throws Exception {
+        HttpConfig testConfig = new HttpConfig();
+        testConfig.setUrl("http://localhost:8080";);
+        testConfig.setUsername("admin");
+        testConfig.setPassword("password");
+
+        Map<String, Object> tokenData = new HashMap<>();
+        tokenData.put("token", "token");
+        tokenData.put("expiredTime", "1800");
+        Map<String, Object> responseMap = new HashMap<>();
+        responseMap.put("data", tokenData);
+        responseMap.put("code", CommonErrorCode.SUCCESSFUL);
+
+        
when(mockOkHttpClient.newCall(any(Request.class))).thenReturn(mockCall);
+        when(mockCall.execute()).thenReturn(mockResponse);
+        when(mockResponse.isSuccessful()).thenReturn(true);
+        when(mockResponse.body()).thenReturn(mockResponseBody);
+        
when(mockResponseBody.string()).thenReturn(GsonUtils.getInstance().toJson(responseMap));
+
+        AccessTokenManager testManager = 
createTestAccessTokenManager(mockOkHttpClient, testConfig);
+        Method doLoginMethod = 
AccessTokenManager.class.getDeclaredMethod("doLogin", String.class);
+        doLoginMethod.setAccessible(true);
+
+        assertFalse((Boolean) doLoginMethod.invoke(testManager, 
"http://localhost:8080";));
+        assertNull(testManager.getAccessToken());
+    }
+
     @Test
     public void testDoLoginIOException() throws Exception {
 

Reply via email to