Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions shenyu-admin/src/http/http-debug-platform-controller-api.http
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@
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;
import org.apache.shenyu.admin.service.EnumService;
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;

/**
Expand All @@ -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())) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<ShenYuResult> response = template.getForEntity(
final String url = baseURL + "/platform/login";
Map<String, String> loginBody = ImmutableMap.<String, String>builder()
.put("userName", loginInfo.get("username"))
.put("password", loginInfo.get("password"))
.build();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(loginBody, headers);
ResponseEntity<ShenYuResult> response = template.postForEntity(
url,
ShenYuResult.class,
loginInfo
requestEntity,
ShenYuResult.class
);
ShenYuResult rst = assertAndGet(response, "login dashboard user success");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public static Optional<Object> doLogin(final String username, final String passw
Map<String, Object> 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<String, Object> resultMap = GsonUtils.getInstance().convertToMap(result);
if (!String.valueOf(CommonErrorCode.SUCCESSFUL).equals(String.valueOf(resultMap.get(Constants.ADMIN_RESULT_CODE)))) {
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -123,7 +124,7 @@ public void testDoLogin() throws IOException {
Map<String, Object> 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<OkHttpTools> okHttpToolsMockedStatic = mockStatic(OkHttpTools.class)) {
okHttpToolsMockedStatic.when(OkHttpTools::getInstance).thenReturn(okHttpTools);
Optional<Object> objectOptional = RegisterUtils.doLogin(userName, password, url);
Expand All @@ -138,7 +139,7 @@ public void testDoLoginError() throws IOException {
Map<String, Object> 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<OkHttpTools> okHttpToolsMockedStatic = mockStatic(OkHttpTools.class)) {
okHttpToolsMockedStatic.when(OkHttpTools::getInstance).thenReturn(okHttpTools);
Optional<Object> objectOptional = RegisterUtils.doLogin(userName, password, url);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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.
*/
Expand Down Expand Up @@ -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<String, String> 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()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -41,16 +42,14 @@

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;
import java.util.Map;
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;
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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<String, Object> 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;
}
}));
Expand Down
Loading
Loading