You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by wu...@apache.org on 2020/12/07 01:34:04 UTC
[shardingsphere-elasticjob] branch master updated: Add cloud
interface authentication (#1764)
This is an automated email from the ASF dual-hosted git repository.
wuweijie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere-elasticjob.git
The following commit(s) were added to refs/heads/master by this push:
new f36dbec Add cloud interface authentication (#1764)
f36dbec is described below
commit f36dbec98210fc8a01b2f3972896e6ecbefbf59b
Author: Yanjie Zhou <zh...@aliyun.com>
AuthorDate: Mon Dec 7 09:26:46 2020 +0800
Add cloud interface authentication (#1764)
* Add cloud interface authentication
* fix code style
---
.../elasticjob/cloud/console/ConsoleBootstrap.java | 3 +
.../console/security/AuthenticationConstants.java | 28 +++++++
.../console/security/AuthenticationFilter.java | 87 ++++++++++++++++++++++
.../cloud/console/security/AuthenticationInfo.java | 31 ++++++++
.../console/security/AuthenticationService.java | 57 ++++++++++++++
.../cloud/scheduler/env/AuthConfiguration.java | 34 +++++++++
.../cloud/scheduler/env/BootstrapEnvironment.java | 15 +++-
.../conf/elasticjob-cloud-scheduler.properties | 6 ++
.../elasticjob/cloud/console/HttpTestUtil.java | 58 ++++++++++++++-
.../cloud/console/controller/CloudLoginTest.java | 67 +++++++++++++++++
10 files changed, 382 insertions(+), 4 deletions(-)
diff --git a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/ConsoleBootstrap.java b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/ConsoleBootstrap.java
index 1b2c324..3c08965 100644
--- a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/ConsoleBootstrap.java
+++ b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/ConsoleBootstrap.java
@@ -21,6 +21,8 @@ import org.apache.shardingsphere.elasticjob.cloud.console.config.advice.ConsoleE
import org.apache.shardingsphere.elasticjob.cloud.console.controller.CloudAppController;
import org.apache.shardingsphere.elasticjob.cloud.console.controller.CloudJobController;
import org.apache.shardingsphere.elasticjob.cloud.console.controller.CloudOperationController;
+import org.apache.shardingsphere.elasticjob.cloud.console.security.AuthenticationFilter;
+import org.apache.shardingsphere.elasticjob.cloud.console.security.AuthenticationService;
import org.apache.shardingsphere.elasticjob.cloud.scheduler.env.RestfulServerConfiguration;
import org.apache.shardingsphere.elasticjob.cloud.scheduler.mesos.ReconcileService;
import org.apache.shardingsphere.elasticjob.cloud.scheduler.producer.ProducerManager;
@@ -43,6 +45,7 @@ public class ConsoleBootstrap {
NettyRestfulServiceConfiguration restfulServiceConfiguration = new NettyRestfulServiceConfiguration(config.getPort());
restfulServiceConfiguration.addControllerInstances(new CloudJobController(), new CloudAppController(), new CloudOperationController());
restfulServiceConfiguration.addExceptionHandler(Exception.class, new ConsoleExceptionHandler());
+ restfulServiceConfiguration.addFilterInstances(new AuthenticationFilter(new AuthenticationService()));
restfulService = new NettyRestfulService(restfulServiceConfiguration);
}
diff --git a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationConstants.java b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationConstants.java
new file mode 100644
index 0000000..1b1c0a2
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationConstants.java
@@ -0,0 +1,28 @@
+/*
+ * 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.shardingsphere.elasticjob.cloud.console.security;
+
+/**
+ * Authentication constants.
+ */
+public final class AuthenticationConstants {
+
+ public static final String LOGIN_URI = "/api/login";
+
+ public static final String HEADER_NAME = "accessToken";
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationFilter.java b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationFilter.java
new file mode 100644
index 0000000..b368a4a
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationFilter.java
@@ -0,0 +1,87 @@
+/*
+ * 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.shardingsphere.elasticjob.cloud.console.security;
+
+import com.google.common.base.Strings;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.FullHttpResponse;
+import io.netty.handler.codec.http.HttpHeaderNames;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.codec.http.HttpUtil;
+import java.util.Collections;
+import java.util.Optional;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.elasticjob.infra.json.GsonFactory;
+import org.apache.shardingsphere.elasticjob.restful.Filter;
+import org.apache.shardingsphere.elasticjob.restful.Http;
+import org.apache.shardingsphere.elasticjob.restful.deserializer.RequestBodyDeserializer;
+import org.apache.shardingsphere.elasticjob.restful.deserializer.RequestBodyDeserializerFactory;
+import org.apache.shardingsphere.elasticjob.restful.filter.FilterChain;
+
+/**
+ * Authentication filter.
+ */
+@RequiredArgsConstructor
+public final class AuthenticationFilter implements Filter {
+
+ private final AuthenticationService authenticationService;
+
+ @Override
+ public void doFilter(final FullHttpRequest httpRequest, final FullHttpResponse httpResponse, final FilterChain filterChain) {
+ if (AuthenticationConstants.LOGIN_URI.equals(httpRequest.uri())) {
+ handleLogin(httpRequest, httpResponse);
+ } else {
+ String accessToken = httpRequest.headers().get(AuthenticationConstants.HEADER_NAME);
+ if (!Strings.isNullOrEmpty(accessToken) && accessToken.equals(authenticationService.getToken())) {
+ filterChain.next(httpRequest);
+ } else {
+ respondWithUnauthorized(httpResponse);
+ }
+ }
+ }
+
+ private void handleLogin(final FullHttpRequest httpRequest, final FullHttpResponse httpResponse) {
+ byte[] bytes = ByteBufUtil.getBytes(httpRequest.content());
+ String mimeType = Optional.ofNullable(HttpUtil.getMimeType(httpRequest))
+ .orElseGet(() -> HttpUtil.getMimeType(Http.DEFAULT_CONTENT_TYPE)).toString();
+ RequestBodyDeserializer deserializer = RequestBodyDeserializerFactory.getRequestBodyDeserializer(mimeType);
+ AuthenticationInfo authenticationInfo = deserializer.deserialize(AuthenticationInfo.class, bytes);
+ boolean result = authenticationService.check(authenticationInfo);
+ if (result) {
+ String token = GsonFactory.getGson().toJson(Collections.singletonMap(AuthenticationConstants.HEADER_NAME,
+ authenticationService.getToken()));
+ respond(httpResponse, HttpResponseStatus.OK, token.getBytes());
+ } else {
+ respondWithUnauthorized(httpResponse);
+ }
+ }
+
+ private void respondWithUnauthorized(final FullHttpResponse httpResponse) {
+ String result = GsonFactory.getGson().toJson(Collections.singletonMap("message", "Unauthorized."));
+ respond(httpResponse, HttpResponseStatus.UNAUTHORIZED, result.getBytes());
+ }
+
+ private void respond(final FullHttpResponse httpResponse, final HttpResponseStatus status, final byte[] result) {
+ httpResponse.setStatus(status);
+ httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, Http.DEFAULT_CONTENT_TYPE);
+ httpResponse.content().writeBytes(result);
+ HttpUtil.setContentLength(httpResponse, httpResponse.content().readableBytes());
+ HttpUtil.setKeepAlive(httpResponse, true);
+ }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationInfo.java b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationInfo.java
new file mode 100644
index 0000000..e4f246f
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationInfo.java
@@ -0,0 +1,31 @@
+/*
+ * 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.shardingsphere.elasticjob.cloud.console.security;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public final class AuthenticationInfo {
+
+ private String username;
+
+ private String password;
+
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationService.java b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationService.java
new file mode 100644
index 0000000..cf6adb9
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/console/security/AuthenticationService.java
@@ -0,0 +1,57 @@
+/*
+ * 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.shardingsphere.elasticjob.cloud.console.security;
+
+import com.google.common.base.Strings;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.shardingsphere.elasticjob.cloud.scheduler.env.AuthConfiguration;
+import org.apache.shardingsphere.elasticjob.cloud.scheduler.env.BootstrapEnvironment;
+import org.apache.shardingsphere.elasticjob.infra.json.GsonFactory;
+
+/**
+ * User authentication service.
+ */
+public final class AuthenticationService {
+
+ private final Base64 base64 = new Base64();
+
+ private final BootstrapEnvironment env = BootstrapEnvironment.getINSTANCE();
+
+ /**
+ * Check auth.
+ *
+ * @param authenticationInfo authentication info
+ * @return check success or failure
+ */
+ public boolean check(final AuthenticationInfo authenticationInfo) {
+ if (null == authenticationInfo || Strings.isNullOrEmpty(authenticationInfo.getUsername()) || Strings.isNullOrEmpty(authenticationInfo.getPassword())) {
+ return false;
+ }
+ AuthConfiguration userAuthConfiguration = env.getUserAuthConfiguration();
+ return userAuthConfiguration.getAuthUsername().equals(authenticationInfo.getUsername()) && userAuthConfiguration.getAuthPassword().equals(authenticationInfo.getPassword());
+ }
+
+ /**
+ * Get user authentication token.
+ *
+ * @return authentication token
+ */
+ public String getToken() {
+ return base64.encodeToString(GsonFactory.getGson().toJson(env.getUserAuthConfiguration()).getBytes());
+ }
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/env/AuthConfiguration.java b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/env/AuthConfiguration.java
new file mode 100644
index 0000000..c11aadd
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/env/AuthConfiguration.java
@@ -0,0 +1,34 @@
+/*
+ * 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.shardingsphere.elasticjob.cloud.scheduler.env;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Auth config.
+ */
+@RequiredArgsConstructor
+@Getter
+public class AuthConfiguration {
+
+ private final String authUsername;
+
+ private final String authPassword;
+
+}
diff --git a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/env/BootstrapEnvironment.java b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/env/BootstrapEnvironment.java
index 8acd829..0e03923 100755
--- a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/env/BootstrapEnvironment.java
+++ b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/java/org/apache/shardingsphere/elasticjob/cloud/scheduler/env/BootstrapEnvironment.java
@@ -121,6 +121,15 @@ public final class BootstrapEnvironment {
public FrameworkConfiguration getFrameworkConfiguration() {
return new FrameworkConfiguration(Integer.parseInt(getValue(EnvironmentArgument.JOB_STATE_QUEUE_SIZE)), Integer.parseInt(getValue(EnvironmentArgument.RECONCILE_INTERVAL_MINUTES)));
}
+
+ /**
+ * Get user auth config.
+ *
+ * @return the user auth config.
+ */
+ public AuthConfiguration getUserAuthConfiguration() {
+ return new AuthConfiguration(getValue(EnvironmentArgument.AUTH_USERNAME), getValue(EnvironmentArgument.AUTH_PASSWORD));
+ }
/**
* Get tracing configuration.
@@ -213,7 +222,11 @@ public final class BootstrapEnvironment {
EVENT_TRACE_RDB_PASSWORD("event_trace_rdb_password", "", false),
- RECONCILE_INTERVAL_MINUTES("reconcile_interval_minutes", "-1", false);
+ RECONCILE_INTERVAL_MINUTES("reconcile_interval_minutes", "-1", false),
+
+ AUTH_USERNAME("auth_username", "root", true),
+
+ AUTH_PASSWORD("auth_password", "pwd", true);
private final String key;
diff --git a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/resources/conf/elasticjob-cloud-scheduler.properties b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/resources/conf/elasticjob-cloud-scheduler.properties
index 7e17d93..6f78c07 100755
--- a/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/resources/conf/elasticjob-cloud-scheduler.properties
+++ b/elasticjob-cloud/elasticjob-cloud-scheduler/src/main/resources/conf/elasticjob-cloud-scheduler.properties
@@ -60,3 +60,9 @@ job_state_queue_size=10000
# Enable/Disable mesos partition aware feature
# enable_partition_aware=false
+
+# Auth username
+auth_username=root
+
+# Auth password
+auth_password=pwd
diff --git a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/HttpTestUtil.java b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/HttpTestUtil.java
index ab0d3a9..16081da 100644
--- a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/HttpTestUtil.java
+++ b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/HttpTestUtil.java
@@ -23,23 +23,34 @@ import java.util.Map;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
+import org.apache.shardingsphere.elasticjob.cloud.console.security.AuthenticationConstants;
+import org.apache.shardingsphere.elasticjob.cloud.console.security.AuthenticationService;
import org.apache.shardingsphere.elasticjob.cloud.scheduler.exception.HttpClientException;
+import org.apache.shardingsphere.elasticjob.infra.json.GsonFactory;
/**
* Http utils.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class HttpTestUtil {
-
+
+ private static final AuthenticationService AUTH_SERVICE = new AuthenticationService();
+
+ private static void setAuth(final HttpRequestBase httpRequestBase) {
+ httpRequestBase.setHeader(AuthenticationConstants.HEADER_NAME, AUTH_SERVICE.getToken());
+ }
+
/**
* Send post request.
*
@@ -49,12 +60,13 @@ public final class HttpTestUtil {
public static int post(final String url) {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost(url);
+ setAuth(httpPost);
return httpClient.execute(httpPost).getStatusLine().getStatusCode();
} catch (IOException e) {
throw new HttpClientException("send a post request for '%s' failed", e, url);
}
}
-
+
/**
* Send post request.
*
@@ -65,6 +77,7 @@ public final class HttpTestUtil {
public static int post(final String url, final String content) {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost(url);
+ setAuth(httpPost);
StringEntity entity = new StringEntity(content, "utf-8");
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
@@ -74,7 +87,7 @@ public final class HttpTestUtil {
throw new HttpClientException("send a post request for '%s' with parameter '%s' failed", e, url, content);
}
}
-
+
/**
* Send put request.
*
@@ -85,6 +98,7 @@ public final class HttpTestUtil {
public static int put(final String url, final String content) {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPut httpPut = new HttpPut(url);
+ setAuth(httpPut);
StringEntity entity = new StringEntity(content, "utf-8");
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
@@ -104,6 +118,7 @@ public final class HttpTestUtil {
public static String get(final String url) {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpGet httpGet = new HttpGet(url);
+ setAuth(httpGet);
HttpEntity entity = httpClient.execute(httpGet).getEntity();
return EntityUtils.toString(entity);
} catch (IOException e) {
@@ -125,6 +140,7 @@ public final class HttpTestUtil {
uriBuilder.addParameter(entry.getKey(), entry.getValue());
}
HttpGet httpGet = new HttpGet(uriBuilder.build());
+ setAuth(httpGet);
HttpEntity entity = httpClient.execute(httpGet).getEntity();
return EntityUtils.toString(entity);
} catch (IOException | URISyntaxException e) {
@@ -141,9 +157,45 @@ public final class HttpTestUtil {
public static int delete(final String url) {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpDelete httpDelete = new HttpDelete(url);
+ setAuth(httpDelete);
return httpClient.execute(httpDelete).getStatusLine().getStatusCode();
} catch (IOException e) {
throw new HttpClientException("send a delete request for '%s' failed", e, url);
}
}
+
+ /**
+ * Send post request.
+ *
+ * @param url url
+ * @param content content
+ * @return http response
+ */
+ public static CloseableHttpResponse unauthorizedPost(final String url, final Map<String, String> content) {
+ try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+ HttpPost httpPost = new HttpPost(url);
+ StringEntity entity = new StringEntity(GsonFactory.getGson().toJson(content), "utf-8");
+ entity.setContentEncoding("UTF-8");
+ entity.setContentType("application/json");
+ httpPost.setEntity(entity);
+ return httpClient.execute(httpPost);
+ } catch (IOException e) {
+ throw new HttpClientException("send a post request for '%s' with parameter '%s' failed", e, url, content);
+ }
+ }
+
+ /**
+ * Send get request.
+ *
+ * @param url url
+ * @return http status code
+ */
+ public static int unauthorizedGet(final String url) {
+ try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+ HttpGet httpGet = new HttpGet(url);
+ return httpClient.execute(httpGet).getStatusLine().getStatusCode();
+ } catch (IOException e) {
+ throw new HttpClientException("send a get request for '%s' failed", e, url);
+ }
+ }
}
diff --git a/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudLoginTest.java b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudLoginTest.java
new file mode 100644
index 0000000..f7e25ee
--- /dev/null
+++ b/elasticjob-cloud/elasticjob-cloud-scheduler/src/test/java/org/apache/shardingsphere/elasticjob/cloud/console/controller/CloudLoginTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.shardingsphere.elasticjob.cloud.console.controller;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.util.EntityUtils;
+import org.apache.shardingsphere.elasticjob.cloud.console.AbstractCloudControllerTest;
+import org.apache.shardingsphere.elasticjob.cloud.console.HttpTestUtil;
+import org.apache.shardingsphere.elasticjob.cloud.console.security.AuthenticationConstants;
+import org.apache.shardingsphere.elasticjob.cloud.console.security.AuthenticationService;
+import org.apache.shardingsphere.elasticjob.infra.json.GsonFactory;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CloudLoginTest extends AbstractCloudControllerTest {
+
+ @Test
+ public void assertLoginSuccess() throws IOException {
+ Map<String, String> authInfo = new HashMap<>();
+ authInfo.put("username", "root");
+ authInfo.put("password", "pwd");
+ CloseableHttpResponse actual = HttpTestUtil.unauthorizedPost("http://127.0.0.1:19000/api/login", authInfo);
+ assertThat(actual.getStatusLine().getStatusCode(), is(200));
+ AuthenticationService authenticationService = new AuthenticationService();
+ String entity = EntityUtils.toString(actual.getEntity());
+ String token = GsonFactory.getGson().fromJson(entity, JsonObject.class).get(AuthenticationConstants.HEADER_NAME).getAsString();
+ assertThat(token, is(authenticationService.getToken()));
+ }
+
+ @Test
+ public void assertLoginFail() {
+ Map<String, String> authInfo = new HashMap<>();
+ authInfo.put("username", "root");
+ authInfo.put("password", "");
+ CloseableHttpResponse actual = HttpTestUtil.unauthorizedPost("http://127.0.0.1:19000/api/login", authInfo);
+ assertThat(actual.getStatusLine().getStatusCode(), is(401));
+ }
+
+ @Test
+ public void assertUnauthorized() {
+ assertThat(HttpTestUtil.unauthorizedGet("http://127.0.0.1:19000/api/unauthorized"), is(401));
+ }
+}