From 4077dd853fefb1b27ff13de33bb411b8682c828a Mon Sep 17 00:00:00 2001 From: eye-gu <734164350@qq.com> Date: Sat, 27 Jun 2026 22:57:13 +0800 Subject: [PATCH] feat: login get to post --- .../http-debug-platform-controller-api.http | 8 +- .../admin/controller/PlatformController.java | 16 ++- .../model/dto/LoginDashboardUserDTO.java | 129 ++++++++++++++++++ .../controller/PlatformControllerTest.java | 8 +- .../shenyu/e2e/client/admin/AdminClient.java | 15 +- .../client/http/utils/RegisterUtils.java | 2 +- .../client/http/utils/RegisterUtilsTest.java | 5 +- .../HttpClientPluginConfigurationTest.java | 2 +- .../sync/data/http/AccessTokenManager.java | 18 ++- .../data/http/AccessTokenManagerTest.java | 24 ++-- .../data/http/HttpSyncDataServiceTest.java | 2 +- 11 files changed, 188 insertions(+), 41 deletions(-) create mode 100644 shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/LoginDashboardUserDTO.java diff --git a/shenyu-admin/src/http/http-debug-platform-controller-api.http b/shenyu-admin/src/http/http-debug-platform-controller-api.http index 6a55c18ebd1f..0e80bbb24f23 100644 --- a/shenyu-admin/src/http/http-debug-platform-controller-api.http +++ b/shenyu-admin/src/http/http-debug-platform-controller-api.http @@ -18,10 +18,14 @@ # if you debug api, replace your own token ### login -GET http://localhost:9095/platform/login?userName=admin&password=123456 +POST http://localhost:9095/platform/login Accept: application/json Content-Type: application/json -X-Access-Token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyTmFtZSI6ImFkbWluIiwiZXhwIjoxNjQ3MDA1ODUxfQ.PQKajtOBgL8_it1Ctylk1-TdBTxFv_fneX1ZPWY4DeE + +{ + "userName": "admin", + "password": "123456" +} ### enum GET http://localhost:9095/platform/enum diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/PlatformController.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/PlatformController.java index 2944a7f89aa5..ae109df52172 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/PlatformController.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/PlatformController.java @@ -18,6 +18,7 @@ package org.apache.shenyu.admin.controller; import org.apache.shenyu.admin.aspect.annotation.RestApi; +import org.apache.shenyu.admin.model.dto.LoginDashboardUserDTO; import org.apache.shenyu.admin.model.result.ShenyuAdminResult; import org.apache.shenyu.admin.model.vo.LoginDashboardUserVO; import org.apache.shenyu.admin.service.DashboardUserService; @@ -25,8 +26,10 @@ import org.apache.shenyu.admin.service.SecretService; import org.apache.shenyu.admin.utils.ShenyuResultMessage; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import jakarta.validation.Valid; import java.util.Optional; /** @@ -50,14 +53,13 @@ public PlatformController(final DashboardUserService dashboardUserService, final /** * login dashboard user. * - * @param userName user name - * @param password user password - * @param clientId client id + * @param loginDashboardUserDTO {@linkplain LoginDashboardUserDTO} * @return {@linkplain ShenyuAdminResult} */ - @GetMapping("/login") - public ShenyuAdminResult loginDashboardUser(final String userName, final String password, @RequestParam(required = false) final String clientId) { - LoginDashboardUserVO loginVO = dashboardUserService.login(userName, password, clientId); + @PostMapping("/login") + public ShenyuAdminResult loginDashboardUser(@RequestBody @Valid final LoginDashboardUserDTO loginDashboardUserDTO) { + LoginDashboardUserVO loginVO = dashboardUserService.login( + loginDashboardUserDTO.getUserName(), loginDashboardUserDTO.getPassword(), loginDashboardUserDTO.getClientId()); return Optional.ofNullable(loginVO) .map(loginStatus -> { if (Boolean.TRUE.equals(loginStatus.getEnabled())) { diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/LoginDashboardUserDTO.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/LoginDashboardUserDTO.java new file mode 100644 index 000000000000..2f4e206e6ec5 --- /dev/null +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/LoginDashboardUserDTO.java @@ -0,0 +1,129 @@ +/* + * 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.shenyu.admin.model.dto; + +import jakarta.validation.constraints.NotBlank; +import java.io.Serializable; +import java.util.Objects; + +/** + * login dashboard user from by web front. + */ +public class LoginDashboardUserDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * user name. + */ + @NotBlank + private String userName; + + /** + * user password (encrypted on the front-end). + */ + @NotBlank + private String password; + + /** + * client id. + */ + private String clientId; + + public LoginDashboardUserDTO() { + } + + public LoginDashboardUserDTO(final String userName, final String password, final String clientId) { + this.userName = userName; + this.password = password; + this.clientId = clientId; + } + + /** + * Gets the value of userName. + * + * @return the value of userName + */ + public String getUserName() { + return userName; + } + + /** + * Sets the userName. + * + * @param userName userName + */ + public void setUserName(final String userName) { + this.userName = userName; + } + + /** + * Gets the value of password. + * + * @return the value of password + */ + public String getPassword() { + return password; + } + + /** + * Sets the password. + * + * @param password password + */ + public void setPassword(final String password) { + this.password = password; + } + + /** + * Gets the value of clientId. + * + * @return the value of clientId + */ + public String getClientId() { + return clientId; + } + + /** + * Sets the clientId. + * + * @param clientId clientId + */ + public void setClientId(final String clientId) { + this.clientId = clientId; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof LoginDashboardUserDTO)) { + return false; + } + LoginDashboardUserDTO that = (LoginDashboardUserDTO) o; + return Objects.equals(userName, that.userName) + && Objects.equals(password, that.password) + && Objects.equals(clientId, that.clientId); + } + + @Override + public int hashCode() { + return Objects.hash(userName, password, clientId); + } +} diff --git a/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/PlatformControllerTest.java b/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/PlatformControllerTest.java index 25dfbba73008..739c5a33225c 100644 --- a/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/PlatformControllerTest.java +++ b/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/PlatformControllerTest.java @@ -32,6 +32,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders; @@ -94,11 +95,14 @@ public void setUp() { */ @Test public void testLoginDashboardUser() throws Exception { - final String loginUri = "/platform/login?userName=" + TEST_LOGIN_USER_NAME + "&password=" + TEST_LOGIN_PASSWORD; + final String loginUri = "/platform/login"; + final String loginRequestBody = String.format("{\"userName\":\"%s\",\"password\":\"%s\"}", TEST_LOGIN_USER_NAME, TEST_LOGIN_PASSWORD); LoginDashboardUserVO loginDashboardUserVO = LoginDashboardUserVO.buildLoginDashboardUserVO(dashboardUserVO); given(this.dashboardUserService.login(eq(TEST_LOGIN_USER_NAME), eq(TEST_LOGIN_PASSWORD), isNull())).willReturn(loginDashboardUserVO); - this.mockMvc.perform(MockMvcRequestBuilders.request(HttpMethod.GET, loginUri)) + this.mockMvc.perform(MockMvcRequestBuilders.post(loginUri) + .contentType(MediaType.APPLICATION_JSON) + .content(loginRequestBody)) .andExpect(status().isOk()) .andExpect(jsonPath("$.code", is(CommonErrorCode.SUCCESSFUL))) .andExpect(jsonPath("$.message", is(ShenyuResultMessage.PLATFORM_LOGIN_SUCCESS))) diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/AdminClient.java b/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/AdminClient.java index 6bac1d572bad..9a90385b250a 100644 --- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/AdminClient.java +++ b/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/AdminClient.java @@ -125,11 +125,18 @@ public AdminClient(final String scenarioId, final String serviceName, final Stri * Login to ShenYu Admin and cache the token. */ public void login() { - final String url = baseURL + "/platform/login?userName={username}&password={password}"; - ResponseEntity response = template.getForEntity( + final String url = baseURL + "/platform/login"; + Map loginBody = ImmutableMap.builder() + .put("userName", loginInfo.get("username")) + .put("password", loginInfo.get("password")) + .build(); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity> requestEntity = new HttpEntity<>(loginBody, headers); + ResponseEntity response = template.postForEntity( url, - ShenYuResult.class, - loginInfo + requestEntity, + ShenYuResult.class ); ShenYuResult rst = assertAndGet(response, "login dashboard user success"); diff --git a/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/main/java/org/apache/shenyu/register/client/http/utils/RegisterUtils.java b/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/main/java/org/apache/shenyu/register/client/http/utils/RegisterUtils.java index 00cb8e280447..4b2afbfb6a2f 100644 --- a/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/main/java/org/apache/shenyu/register/client/http/utils/RegisterUtils.java +++ b/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/main/java/org/apache/shenyu/register/client/http/utils/RegisterUtils.java @@ -141,7 +141,7 @@ public static Optional doLogin(final String username, final String passw Map loginMap = new HashMap<>(2); loginMap.put(Constants.LOGIN_NAME, username); loginMap.put(Constants.PASS_WORD, password); - String result = OkHttpTools.getInstance().get(url, loginMap); + String result = OkHttpTools.getInstance().post(url, GsonUtils.getInstance().toJson(loginMap)); Map resultMap = GsonUtils.getInstance().convertToMap(result); if (!String.valueOf(CommonErrorCode.SUCCESSFUL).equals(String.valueOf(resultMap.get(Constants.ADMIN_RESULT_CODE)))) { return Optional.empty(); diff --git a/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/test/java/org/apache/shenyu/register/client/http/utils/RegisterUtilsTest.java b/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/test/java/org/apache/shenyu/register/client/http/utils/RegisterUtilsTest.java index a61b18fe667f..151f0ac6f9f5 100644 --- a/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/test/java/org/apache/shenyu/register/client/http/utils/RegisterUtilsTest.java +++ b/shenyu-register-center/shenyu-register-client/shenyu-register-client-http/src/test/java/org/apache/shenyu/register/client/http/utils/RegisterUtilsTest.java @@ -20,6 +20,7 @@ import com.google.gson.Gson; import okhttp3.Headers; import org.apache.shenyu.common.constant.Constants; +import org.apache.shenyu.common.utils.GsonUtils; import org.apache.shenyu.register.common.enums.RegisterTypeEnum; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -123,7 +124,7 @@ public void testDoLogin() throws IOException { Map loginMap = new HashMap<>(2); loginMap.put(Constants.LOGIN_NAME, userName); loginMap.put(Constants.PASS_WORD, password); - when(okHttpTools.get(url, loginMap)).thenReturn("{\"code\":200,\"data\":{\"token\":\"" + token + "\"}}"); + when(okHttpTools.post(url, GsonUtils.getInstance().toJson(loginMap))).thenReturn("{\"code\":200,\"data\":{\"token\":\"" + token + "\"}}"); try (MockedStatic okHttpToolsMockedStatic = mockStatic(OkHttpTools.class)) { okHttpToolsMockedStatic.when(OkHttpTools::getInstance).thenReturn(okHttpTools); Optional objectOptional = RegisterUtils.doLogin(userName, password, url); @@ -138,7 +139,7 @@ public void testDoLoginError() throws IOException { Map loginMap = new HashMap<>(2); loginMap.put(Constants.LOGIN_NAME, userName); loginMap.put(Constants.PASS_WORD, password); - when(okHttpTools.get(url, loginMap)).thenReturn("{\"code\":300}"); + when(okHttpTools.post(url, GsonUtils.getInstance().toJson(loginMap))).thenReturn("{\"code\":300}"); try (MockedStatic okHttpToolsMockedStatic = mockStatic(OkHttpTools.class)) { okHttpToolsMockedStatic.when(OkHttpTools::getInstance).thenReturn(okHttpTools); Optional objectOptional = RegisterUtils.doLogin(userName, password, url); diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-sync-data-center/shenyu-spring-boot-starter-sync-data-http/src/test/java/org/apache/shenyu/springboot/starter/sync/data/http/HttpClientPluginConfigurationTest.java b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-sync-data-center/shenyu-spring-boot-starter-sync-data-http/src/test/java/org/apache/shenyu/springboot/starter/sync/data/http/HttpClientPluginConfigurationTest.java index d99298f6e9b3..528fcc9f9c6f 100644 --- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-sync-data-center/shenyu-spring-boot-starter-sync-data-http/src/test/java/org/apache/shenyu/springboot/starter/sync/data/http/HttpClientPluginConfigurationTest.java +++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-sync-data-center/shenyu-spring-boot-starter-sync-data-http/src/test/java/org/apache/shenyu/springboot/starter/sync/data/http/HttpClientPluginConfigurationTest.java @@ -82,7 +82,7 @@ public final class HttpClientPluginConfigurationTest { public static void setUpWireMock() throws Exception { WireMockServer wireMockServer = new WireMockServer(options().port(18848)); - wireMockServer.stubFor(get(urlPathEqualTo("/platform/login")) + wireMockServer.stubFor(post(urlPathEqualTo("/platform/login")) .willReturn(aResponse() .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()) .withBody(mockLoginResponseJson()) 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 3f26558119f1..cd762347ce67 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 @@ -19,8 +19,10 @@ import com.google.common.base.Splitter; import com.google.common.collect.Lists; +import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; +import okhttp3.RequestBody; import okhttp3.Response; import okhttp3.ResponseBody; import org.apache.commons.lang3.StringUtils; @@ -35,8 +37,7 @@ import org.springframework.util.Assert; import java.io.IOException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ScheduledExecutorService; @@ -50,6 +51,8 @@ public class AccessTokenManager { public static final Logger LOG = LoggerFactory.getLogger(AccessTokenManager.class); + private static final MediaType JSON_MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8"); + /** * the access token. */ @@ -113,11 +116,12 @@ private Boolean doLogin(final String server) { password = AesUtils.cbcEncrypt(httpConfig.getAesSecretKey(), httpConfig.getAesSecretIv(), httpConfig.getPassword()); } - String encodedUsername = URLEncoder.encode(httpConfig.getUsername(), StandardCharsets.UTF_8); - String encodedPassword = URLEncoder.encode(password, StandardCharsets.UTF_8); - String param = Constants.LOGIN_NAME + "=" + encodedUsername + "&" + Constants.PASS_WORD + "=" + encodedPassword; - String url = String.join("?", server + Constants.LOGIN_PATH, param); - Request request = new Request.Builder().url(url).build(); + Map loginBody = new HashMap<>(2); + loginBody.put(Constants.LOGIN_NAME, httpConfig.getUsername()); + loginBody.put(Constants.PASS_WORD, password); + RequestBody requestBody = RequestBody.create(GsonUtils.getInstance().toJson(loginBody), JSON_MEDIA_TYPE); + String url = server + Constants.LOGIN_PATH; + Request request = new Request.Builder().url(url).post(requestBody).build(); try (Response response = this.okHttpClient.newCall(request).execute()) { if (!response.isSuccessful()) { 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 824189b816a3..98c0379171c8 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 @@ -25,6 +25,7 @@ import okhttp3.Request; import okhttp3.Response; import okhttp3.ResponseBody; +import org.apache.shenyu.common.constant.Constants; import org.apache.shenyu.common.constant.HttpConstants; import org.apache.shenyu.common.exception.CommonErrorCode; import org.apache.shenyu.common.utils.GsonUtils; @@ -41,8 +42,6 @@ import java.io.IOException; import java.lang.reflect.Method; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.HashMap; import java.util.List; @@ -50,7 +49,7 @@ import java.util.Objects; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.post; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -102,7 +101,7 @@ public void before() { .extensions(mock(ResponseTemplateTransformer.class)) .dynamicPort()); this.wireMockServer.start(); - wireMockServer.stubFor(get(urlPathEqualTo("/platform/login")) + wireMockServer.stubFor(post(urlPathEqualTo("/platform/login")) .willReturn(aResponse() .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()) .withBody(this.mockLoginResponseJson()) @@ -134,7 +133,7 @@ public void testLogin() { } @Test - public void testDoLoginWithUrlEncodingAndSpecialCharacters() throws Exception { + public void testDoLoginWithSpecialCharactersInRequestBody() throws Exception { HttpConfig testConfig = new HttpConfig(); testConfig.setUrl("http://localhost:8080"); @@ -166,17 +165,14 @@ public void testDoLoginWithUrlEncodingAndSpecialCharacters() throws Exception { assertEquals("special-token", testManager.getAccessToken()); verify(mockOkHttpClient, times(2)).newCall(argThat(request -> { - - String url = request.url().toString(); - try { - String expectedUsername = URLEncoder.encode("test user@domain.com", StandardCharsets.UTF_8); - String expectedPassword = URLEncoder.encode("pass+word=123&456 789%test", StandardCharsets.UTF_8); - - return url.contains("userName=" + expectedUsername) - && url.contains("password=" + expectedPassword); + okio.Buffer buffer = new okio.Buffer(); + request.body().writeTo(buffer); + Map bodyMap = GsonUtils.getInstance().convertToMap(buffer.readUtf8()); + return "test user@domain.com".equals(bodyMap.get(Constants.LOGIN_NAME)) + && "pass+word=123&456 789%test".equals(bodyMap.get(Constants.PASS_WORD)); } catch (Exception e) { - LOG.error("URL encoding test failed", e); + LOG.error("request body inspection failed", e); return false; } })); diff --git a/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/HttpSyncDataServiceTest.java b/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/HttpSyncDataServiceTest.java index d0df2b368458..4754feabffeb 100644 --- a/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/HttpSyncDataServiceTest.java +++ b/shenyu-sync-data-center/shenyu-sync-data-http/src/test/java/org/apache/shenyu/sync/data/http/HttpSyncDataServiceTest.java @@ -95,7 +95,7 @@ public void before() { .extensions(mock(ResponseTemplateTransformer.class)) .dynamicPort()); this.wireMockServer.start(); - wireMockServer.stubFor(get(urlPathEqualTo("/platform/login")) + wireMockServer.stubFor(post(urlPathEqualTo("/platform/login")) .willReturn(aResponse() .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()) .withBody(this.mockLoginResponseJson())