Revise cloud scheduler authentication (#1766)

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
index 1b1c0a2..e42064b 100644
--- 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
@@ -17,12 +17,16 @@
 
 package org.apache.shardingsphere.elasticjob.cloud.console.security;
 
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
 /**
  * Authentication constants.
  */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 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
index b368a4a..60da27f 100644
--- 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
@@ -18,65 +18,68 @@
 package org.apache.shardingsphere.elasticjob.cloud.console.security;
 
 import com.google.common.base.Strings;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 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.HttpMethod;
 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;
 
+import java.util.Collections;
+import java.util.Optional;
+
 /**
  * Authentication filter.
  */
 @RequiredArgsConstructor
 public final class AuthenticationFilter implements Filter {
-
+    
+    private final Gson gson = new GsonBuilder().disableHtmlEscaping().create();
+    
     private final AuthenticationService authenticationService;
-
+    
     @Override
     public void doFilter(final FullHttpRequest httpRequest, final FullHttpResponse httpResponse, final FilterChain filterChain) {
-        if (AuthenticationConstants.LOGIN_URI.equals(httpRequest.uri())) {
+        if (HttpMethod.POST.equals(httpRequest.method()) && 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);
-            }
+            return;
         }
+        String accessToken = httpRequest.headers().get(AuthenticationConstants.HEADER_NAME);
+        if (Strings.isNullOrEmpty(accessToken) || !accessToken.equals(authenticationService.getToken())) {
+            respondWithUnauthorized(httpResponse);
+            return;
+        }
+        filterChain.next(httpRequest);
     }
-
+    
     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();
+        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 {
+        if (!result) {
             respondWithUnauthorized(httpResponse);
+            return;
         }
+        String token = gson.toJson(Collections.singletonMap(AuthenticationConstants.HEADER_NAME, authenticationService.getToken()));
+        respond(httpResponse, HttpResponseStatus.OK, token.getBytes());
     }
-
+    
     private void respondWithUnauthorized(final FullHttpResponse httpResponse) {
-        String result = GsonFactory.getGson().toJson(Collections.singletonMap("message", "Unauthorized."));
+        String result = gson.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);
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
index e4f246f..a0d0da8 100644
--- 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
@@ -20,12 +20,14 @@
 import lombok.Getter;
 import lombok.Setter;
 
+/**
+ * Authentication info.
+ */
 @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
index cf6adb9..a07cf58 100644
--- 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
@@ -18,20 +18,23 @@
 package org.apache.shardingsphere.elasticjob.cloud.console.security;
 
 import com.google.common.base.Strings;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 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 Gson gson = new GsonBuilder().disableHtmlEscaping().create();
+    
     private final Base64 base64 = new Base64();
-
+    
     private final BootstrapEnvironment env = BootstrapEnvironment.getINSTANCE();
-
+    
     /**
      * Check auth.
      *
@@ -45,13 +48,13 @@
         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());
+        return base64.encodeToString(gson.toJson(env.getUserAuthConfiguration()).getBytes());
     }
 }
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 16081da..df71491 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
@@ -44,13 +44,13 @@
  */
 @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.
      *
@@ -66,11 +66,11 @@
             throw new HttpClientException("send a post request for '%s' failed", e, url);
         }
     }
-
+    
     /**
      * Send post request.
      *
-     * @param url url
+     * @param url     url
      * @param content content
      * @return http status code
      */
@@ -87,11 +87,11 @@
             throw new HttpClientException("send a post request for '%s' with parameter '%s' failed", e, url, content);
         }
     }
-
+    
     /**
      * Send put request.
      *
-     * @param url url
+     * @param url     url
      * @param content content
      * @return http status code
      */
@@ -129,7 +129,7 @@
     /**
      * Send get request.
      *
-     * @param url url
+     * @param url     url
      * @param content content
      * @return http result
      */
@@ -163,11 +163,11 @@
             throw new HttpClientException("send a delete request for '%s' failed", e, url);
         }
     }
-
+    
     /**
      * Send post request.
      *
-     * @param url url
+     * @param url     url
      * @param content content
      * @return http response
      */
@@ -183,7 +183,7 @@
             throw new HttpClientException("send a post request for '%s' with parameter '%s' failed", e, url, content);
         }
     }
-
+    
     /**
      * Send get request.
      *
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
index f7e25ee..7ff5229 100644
--- 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
@@ -17,13 +17,7 @@
 
 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;
@@ -35,6 +29,13 @@
 import org.junit.runner.RunWith;
 import org.mockito.junit.MockitoJUnitRunner;
 
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
 @RunWith(MockitoJUnitRunner.class)
 public class CloudLoginTest extends AbstractCloudControllerTest {
     
@@ -50,7 +51,7 @@
         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<>();
@@ -59,7 +60,7 @@
         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));