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 {