SUBMARINE-1294. Add simple type authentication for REST api

### What is this PR for?
Add simple type authentication for REST api.
Use [pac4j](https://www.pac4j.org/index.html) for token generation and validation. Considering need to adapt to java8, this PR is using 4.5.6 instead of version pac4j 5 for the time being.

### What type of PR is it?
Feature

### Todos
* [x] - Add some configs for authentication
* [x] - Add `SimpleFilter`
* [x] - Modified some login api processing logic (no logout available yet)
* [x] - Add test case

### What is the Jira issue?
https://issues.apache.org/jira/projects/SUBMARINE/issues/SUBMARINE-1294

### How should this be tested?
Have added a test case in `org.apache.submarine.server.security.SubmarineAuthSimpleTest`

### Screenshots (if appropriate)
No

### Questions:
* Do the license files need updating? No
* Are there breaking changes for older versions? Yes
* Does this need new documentation? Yes(link: https://github.com/apache/submarine/pull/975)

Author: cdmikechen <cdmikechen@hotmail.com>

Signed-off-by: Kevin <pingsutw@apache.org>

Closes #979 from cdmikechen/SUBMARINE-1294 and squashes the following commits:

2fff5bdc [cdmikechen] add a test user
b5d9b46c [cdmikechen] get config realtime
7c2b29fe [cdmikechen] init provider
0105bac5 [cdmikechen] remove some test
e0e0c25b [cdmikechen] change pc4j to 4.5.6 for adaptation of java8
909ffa9b [cdmikechen] Fist commit with pc4j 5.4.3 and test case
diff --git a/dev-support/database/submarine-data.sql b/dev-support/database/submarine-data.sql
index 3a767d3..423aee8 100644
--- a/dev-support/database/submarine-data.sql
+++ b/dev-support/database/submarine-data.sql
@@ -53,7 +53,7 @@
 -- ----------------------------
 -- Records of sys_user
 -- ----------------------------
-INSERT INTO `sys_user` VALUES ('e9ca23d68d884d4ebb19d07889727dae', 'admin', 'administrator', '21232f297a57a5a743894a0e4a801fc3', 'avatar.png', '2018-12-05 00:00:00', NULL, 'dev@submarine.org', '18566666661', NULL, NULL, NULL, 1, 'admin', '2019-07-05 14:47:22', 'admin', '2019-07-05 14:47:22');
+INSERT INTO `sys_user` VALUES ('e9ca23d68d884d4ebb19d07889727dae', 'admin', 'administrator', '21232f297a57a5a743894a0e4a801fc3', 'avatar.png', '2018-12-05 00:00:00', NULL, 'dev@submarine.org', '18566666661', NULL, NULL, NULL, 0, 'admin', now(), 'admin', now());
 
 -- ----------------------------
 -- Records of team
diff --git a/pom.xml b/pom.xml
index 301decd..ad2f20c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -148,6 +148,8 @@
     <!--  server API  -->
     <protobuf-java.version>3.14.0</protobuf-java.version>
     <joda-time.version>2.10.8</joda-time.version>
+    <!--  pac4j  -->
+    <pac4j.version>4.5.6</pac4j.version>
   </properties>
 
   <modules>
diff --git a/submarine-commons/commons-utils/src/main/java/org/apache/submarine/commons/utils/SubmarineConfVars.java b/submarine-commons/commons-utils/src/main/java/org/apache/submarine/commons/utils/SubmarineConfVars.java
index a96a885..9d1a403 100644
--- a/submarine-commons/commons-utils/src/main/java/org/apache/submarine/commons/utils/SubmarineConfVars.java
+++ b/submarine-commons/commons-utils/src/main/java/org/apache/submarine/commons/utils/SubmarineConfVars.java
@@ -75,7 +75,12 @@
     SUBMARINE_SUBMITTER("submarine.submitter", "k8s"),
     SUBMARINE_SERVER_SERVICE_NAME("submarine.server.service.name", "submarine-server"),
     ENVIRONMENT_CONDA_MIN_VERSION("environment.conda.min.version", "4.0.1"),
-    ENVIRONMENT_CONDA_MAX_VERSION("environment.conda.max.version", "4.11.10");
+    ENVIRONMENT_CONDA_MAX_VERSION("environment.conda.max.version", "4.11.10"),
+
+    /* auth */
+    SUBMARINE_AUTH_TYPE("submarine.auth.type", "none"),
+    SUBMARINE_AUTH_DEFAULT_SECRET("submarine.auth.default.secret", "SUBMARINE_SECRET_12345678901234567890"),
+    SUBMARINE_AUTH_MAX_AGE_ENV("submarine.auth.maxAge", 60 * 60 * 24);
 
     private String varName;
     @SuppressWarnings("rawtypes")
diff --git a/submarine-server/server-core/pom.xml b/submarine-server/server-core/pom.xml
index f891f5e..d33ff94 100644
--- a/submarine-server/server-core/pom.xml
+++ b/submarine-server/server-core/pom.xml
@@ -427,6 +427,34 @@
       <artifactId>joda-time</artifactId>
     </dependency>
 
+    <dependency>
+      <groupId>org.pac4j</groupId>
+      <artifactId>pac4j-http</artifactId>
+      <version>${pac4j.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>com.fasterxml.jackson.core</groupId>
+          <artifactId>jackson-databind</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.pac4j</groupId>
+      <artifactId>pac4j-jwt</artifactId>
+      <version>${pac4j.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>org.bouncycastle</groupId>
+          <artifactId>bcprov-jdk15on</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.ow2.asm</groupId>
+          <artifactId>asm</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
   </dependencies>
 
   <build>
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/SubmarineServer.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/SubmarineServer.java
index 4eccbb5..4449880 100644
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/SubmarineServer.java
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/SubmarineServer.java
@@ -20,6 +20,8 @@
 
 import org.apache.log4j.PropertyConfigurator;
 import org.apache.submarine.server.rest.provider.YamlEntityProvider;
+import org.apache.submarine.server.security.SecurityFactory;
+import org.apache.submarine.server.security.SecurityProvider;
 import org.apache.submarine.server.workbench.websocket.NotebookServer;
 import org.apache.submarine.server.websocket.WebSocketServer;
 import org.eclipse.jetty.http.HttpVersion;
@@ -53,6 +55,8 @@
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
+import javax.servlet.DispatcherType;
+import javax.servlet.Filter;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
@@ -62,6 +66,8 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.util.EnumSet;
+import java.util.Optional;
 
 public class SubmarineServer extends ResourceConfig {
   private static final Logger LOG = LoggerFactory.getLogger(SubmarineServer.class);
@@ -201,6 +207,14 @@
     webApp.addServlet(new ServletHolder(RefreshServlet.class), "/user/*");
     webApp.addServlet(new ServletHolder(RefreshServlet.class), "/workbench/*");
 
+    // add security filter
+    Optional<SecurityProvider> securityProvider = SecurityFactory.getSecurityProvider();
+    if (securityProvider.isPresent()) {
+      Class<Filter> filterClass = securityProvider.get().getFilterClass();
+      LOG.info("Add {} to support auth", filterClass);
+      webApp.addFilter(filterClass, "/*", EnumSet.of(DispatcherType.REQUEST));
+    }
+
     handlers.setHandlers(new Handler[]{webApp});
 
     return webApp;
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/workbench/LoginRestApi.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/workbench/LoginRestApi.java
index 54abc57..f385a99 100644
--- a/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/workbench/LoginRestApi.java
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/workbench/LoginRestApi.java
@@ -25,6 +25,8 @@
 import org.apache.submarine.server.database.workbench.entity.SysUserEntity;
 import org.apache.submarine.server.database.workbench.mappers.SysUserMapper;
 import org.apache.submarine.server.database.utils.MyBatisUtil;
+import org.apache.submarine.server.security.common.CommonConfig;
+import org.apache.submarine.server.security.simple.SimpleLoginConfig;
 import org.apache.submarine.server.utils.response.JsonResponse;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -35,6 +37,7 @@
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.Response;
+import java.util.Date;
 import java.util.HashMap;
 
 @Path("/auth")
@@ -60,16 +63,61 @@
       SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);
       sysUser = sysUserMapper.login(mapParams);
       if (sysUser != null) {
-        sysUser.setToken("mock_token");
+        HashMap<String, Object> claimsMap = new HashMap<>();
+        claimsMap.put("username", sysUser.getUserName());
+        claimsMap.put("realName", sysUser.getRealName());
+        claimsMap.put("password", sysUser.getPassword());
+        claimsMap.put("avatar", sysUser.getAvatar());
+        claimsMap.put("sex", sysUser.getSex());
+        claimsMap.put("status", sysUser.getStatus());
+        claimsMap.put("phone", sysUser.getPhone());
+        claimsMap.put("email", sysUser.getEmail());
+        claimsMap.put("deptCode", sysUser.getDeptCode());
+        claimsMap.put("deptName", sysUser.getDeptName());
+        claimsMap.put("roleCode", sysUser.getRoleCode());
+        claimsMap.put("birthday", sysUser.getBirthday());
+        claimsMap.put("iat", new Date().getTime());
+        claimsMap.put("exp", new Date().getTime() + CommonConfig.MAX_AGE);
+        claimsMap.put("sub", "submarine");
+        claimsMap.put("jti", sysUser.getId());
+
+        String token = SimpleLoginConfig.getJwtGenerator().generate(claimsMap);
+        sysUser.setToken(token);
       } else {
-        LOG.info("User Not Found. Please try again");
+        LOG.warn("Can not find user {}", mapParams);
+        return new JsonResponse.Builder<>(Response.Status.UNAUTHORIZED)
+            .message("User Not Found. Please try again!")
+            .success(false)
+            .build();
       }
     } catch (Exception e) {
       LOG.error(e.getMessage(), e);
-      return new JsonResponse.Builder<>(Response.Status.OK).success(false).build();
+      return new JsonResponse.Builder<>(Response.Status.OK)
+          .message(e.getMessage())
+          .success(false)
+          .build();
     }
 
-    return new JsonResponse.Builder<SysUserEntity>(Response.Status.OK).success(true).result(sysUser).build();
+    return new JsonResponse.Builder<SysUserEntity>(Response.Status.OK)
+        .message("Login successfully!")
+        .success(true)
+        .result(sysUser)
+        .build();
+  }
+
+  /**
+   * Get user by unique name
+   */
+  public SysUserEntity getUserByName(String name) throws Exception {
+    SysUserEntity sysUser = null;
+    try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
+      SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);
+      sysUser = sysUserMapper.getUserByUniqueName(name);
+    } catch (Exception e) {
+      LOG.error(e.getMessage(), e);
+      throw new Exception(e);
+    }
+    return sysUser;
   }
 
   @POST
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/SecurityFactory.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/SecurityFactory.java
new file mode 100644
index 0000000..d223244
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/SecurityFactory.java
@@ -0,0 +1,63 @@
+/*
+ * 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.submarine.server.security;
+
+import org.apache.submarine.commons.utils.SubmarineConfVars;
+import org.apache.submarine.commons.utils.SubmarineConfiguration;
+import org.apache.submarine.server.security.simple.SimpleSecurityProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+public class SecurityFactory {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SecurityFactory.class);
+
+  private static final Map<String, SecurityProvider> providerMap;
+
+  public static SimpleSecurityProvider getSimpleSecurityProvider() {
+    return (SimpleSecurityProvider) providerMap.get("simple");
+  }
+
+  static {
+    // int provider map
+    providerMap = new HashMap<>();
+    providerMap.put("simple", new SimpleSecurityProvider());
+  }
+
+  public static void addProvider(String name, SecurityProvider provider) {
+    providerMap.put(name, provider);
+  }
+
+  public static Optional<SecurityProvider> getSecurityProvider() {
+    String authType = SubmarineConfiguration.getInstance()
+        .getString(SubmarineConfVars.ConfVars.SUBMARINE_AUTH_TYPE);
+    if (providerMap.containsKey(authType)) {
+      return Optional.ofNullable(providerMap.get(authType));
+    } else {
+      LOG.warn("current auth type is {} but we can not recognize, so use none!", authType);
+      return Optional.empty();
+    }
+  }
+
+}
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/SecurityProvider.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/SecurityProvider.java
new file mode 100644
index 0000000..c775705
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/SecurityProvider.java
@@ -0,0 +1,61 @@
+/*
+ * 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.submarine.server.security;
+
+import org.pac4j.core.config.Config;
+import org.pac4j.core.profile.CommonProfile;
+
+import javax.servlet.Filter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Optional;
+
+/**
+ * Provide security methods for different authentication types
+ */
+public interface SecurityProvider<T extends Filter, R extends CommonProfile> {
+
+  String DEFAULT_AUTHORIZER = "isAuthenticated";
+
+  /**
+   * Get filter class
+   */
+  Class<T> getFilterClass();
+
+  /**
+   * Get pac4j config
+   */
+  Config getConfig();
+
+  /**
+   * Get pac4j client
+   */
+  String getClient(HttpServletRequest httpServletRequest);
+
+  /**
+   * Process authentication information and return user profile
+   */
+  Optional<R> perform(HttpServletRequest hsRequest, HttpServletResponse hsResponse);
+
+  /**
+   * Get user profile
+   */
+  Optional<R> getProfile(HttpServletRequest hsRequest, HttpServletResponse hsResponse);
+}
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/common/CommonConfig.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/common/CommonConfig.java
new file mode 100644
index 0000000..83f1bb8
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/common/CommonConfig.java
@@ -0,0 +1,39 @@
+/*
+ * 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.submarine.server.security.common;
+
+import org.apache.submarine.commons.utils.SubmarineConfiguration;
+
+import static org.apache.submarine.commons.utils.SubmarineConfVars.ConfVars;
+
+public class CommonConfig {
+
+  public static final String LOGOUT_ENDPOINT = "/auth/logout";
+  public static final String AUTH_HEADER = "Authorization";
+  public static final String BEARER_HEADER_PREFIX = "Bearer ";
+
+  public static final int MAX_AGE;
+
+  static {
+    SubmarineConfiguration conf = SubmarineConfiguration.getInstance();
+    MAX_AGE = conf.getInt(ConfVars.SUBMARINE_AUTH_MAX_AGE_ENV);
+  }
+
+}
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/common/CommonFilter.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/common/CommonFilter.java
new file mode 100644
index 0000000..a0a0fdc
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/common/CommonFilter.java
@@ -0,0 +1,46 @@
+/*
+ * 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.submarine.server.security.common;
+
+import org.pac4j.core.context.JEEContext;
+import org.pac4j.core.context.session.JEESessionStore;
+import org.pac4j.core.context.session.SessionStore;
+import org.pac4j.core.engine.DefaultCallbackLogic;
+import org.pac4j.core.engine.DefaultLogoutLogic;
+import org.pac4j.core.engine.DefaultSecurityLogic;
+import org.pac4j.core.http.adapter.HttpActionAdapter;
+import org.pac4j.core.http.adapter.JEEHttpActionAdapter;
+import org.pac4j.core.profile.CommonProfile;
+import org.pac4j.core.profile.UserProfile;
+
+public class CommonFilter {
+
+  public static final HttpActionAdapter DEFAULT_HTTP_ACTION_ADAPTER = JEEHttpActionAdapter.INSTANCE;
+
+  public static final DefaultCallbackLogic<CommonProfile, JEEContext> CALLBACK_LOGIC =
+          new DefaultCallbackLogic<>();
+
+  public static final DefaultSecurityLogic<UserProfile, JEEContext> SECURITY_LOGIC =
+          new DefaultSecurityLogic<>();
+
+  public static final DefaultLogoutLogic<UserProfile, JEEContext> LOGOUT_LOGIC = new DefaultLogoutLogic<>();
+
+  public static final SessionStore<JEEContext> SESSION_STORE = new JEESessionStore();
+}
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/simple/SimpleFilter.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/simple/SimpleFilter.java
new file mode 100644
index 0000000..4bb9198
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/simple/SimpleFilter.java
@@ -0,0 +1,75 @@
+/*
+ * 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.submarine.server.security.simple;
+
+import org.apache.submarine.server.security.SecurityFactory;
+import org.apache.submarine.server.security.common.CommonFilter;
+import org.pac4j.jwt.profile.JwtProfile;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Optional;
+
+/**
+ * Simple authentication
+ * Only users in submarine sys_user table can log in, and user is verified based on token
+ */
+public class SimpleFilter extends CommonFilter implements Filter {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SimpleFilter.class);
+
+  private final SimpleSecurityProvider provider;
+
+  public SimpleFilter() {
+    this.provider = SecurityFactory.getSimpleSecurityProvider();
+  }
+
+  @Override
+  public void init(FilterConfig filterConfig) throws ServletException {
+  }
+
+  @Override
+  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+                       FilterChain filterChain) throws IOException, ServletException {
+    HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
+    HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
+    // check header token
+    Optional<JwtProfile> profile = provider.perform(httpServletRequest, httpServletResponse);
+    // If the token can be correctly parsed then continue processing, otherwise return 401
+    if (profile.isPresent()) {
+      filterChain.doFilter(servletRequest, servletResponse);
+    } else {
+      httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "The token is not valid.");
+    }
+  }
+
+  @Override
+  public void destroy() {
+  }
+}
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/simple/SimpleLoginConfig.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/simple/SimpleLoginConfig.java
new file mode 100644
index 0000000..e1e2939
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/simple/SimpleLoginConfig.java
@@ -0,0 +1,55 @@
+/*
+ * 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.submarine.server.security.simple;
+
+import org.apache.submarine.commons.utils.SubmarineConfiguration;
+import org.apache.submarine.server.security.common.CommonConfig;
+import org.pac4j.jwt.config.encryption.SecretEncryptionConfiguration;
+import org.pac4j.jwt.config.signature.SecretSignatureConfiguration;
+import org.pac4j.jwt.credentials.authenticator.JwtAuthenticator;
+import org.pac4j.jwt.profile.JwtGenerator;
+
+import static org.apache.submarine.commons.utils.SubmarineConfVars.ConfVars;
+
+public class SimpleLoginConfig extends CommonConfig {
+
+  private static final String SUBMARINE_SECRET;
+  private static final JwtAuthenticator JWT_AUTHENTICATOR;
+  private static final JwtGenerator JWT_GENERATOR;
+
+  static {
+    SubmarineConfiguration conf = SubmarineConfiguration.getInstance();
+    // Generating the token requires a secret key,
+    // if the user does not provide the secret key, we will use the default secret key
+    SUBMARINE_SECRET = conf.getString(ConfVars.SUBMARINE_AUTH_DEFAULT_SECRET);
+    JWT_AUTHENTICATOR = new JwtAuthenticator(
+            new SecretSignatureConfiguration(SUBMARINE_SECRET),
+            new SecretEncryptionConfiguration(SUBMARINE_SECRET));
+    JWT_GENERATOR = new JwtGenerator(new SecretSignatureConfiguration(SUBMARINE_SECRET));
+  }
+
+  public static JwtAuthenticator getJwtAuthenticator() {
+    return JWT_AUTHENTICATOR;
+  }
+
+  public static JwtGenerator getJwtGenerator() {
+    return JWT_GENERATOR;
+  }
+}
diff --git a/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/simple/SimpleSecurityProvider.java b/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/simple/SimpleSecurityProvider.java
new file mode 100644
index 0000000..3a35166
--- /dev/null
+++ b/submarine-server/server-core/src/main/java/org/apache/submarine/server/security/simple/SimpleSecurityProvider.java
@@ -0,0 +1,102 @@
+/*
+ * 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.submarine.server.security.simple;
+
+import org.apache.submarine.server.security.SecurityProvider;
+import org.apache.submarine.server.security.common.CommonConfig;
+import org.apache.submarine.server.security.common.CommonFilter;
+import org.pac4j.core.config.Config;
+import org.pac4j.core.context.JEEContext;
+import org.pac4j.core.matching.matcher.PathMatcher;
+import org.pac4j.core.profile.ProfileManager;
+import org.pac4j.core.profile.UserProfile;
+import org.pac4j.http.client.direct.HeaderClient;
+import org.pac4j.jwt.profile.JwtProfile;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Collection;
+import java.util.Optional;
+
+public class SimpleSecurityProvider implements SecurityProvider<SimpleFilter, JwtProfile> {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SimpleSecurityProvider.class);
+
+  private Config pac4jConfig;
+
+  @Override
+  public Class<SimpleFilter> getFilterClass() {
+    return SimpleFilter.class;
+  }
+
+  @Override
+  public Config getConfig() {
+    if (pac4jConfig != null) {
+      return pac4jConfig;
+    }
+
+    // header client
+    HeaderClient headerClient = new HeaderClient(CommonConfig.AUTH_HEADER, CommonConfig.BEARER_HEADER_PREFIX,
+            SimpleLoginConfig.getJwtAuthenticator());
+
+    Config pac4jConfig = new Config(headerClient);
+    // skip web static resources
+    pac4jConfig.addMatcher("static", new PathMatcher().excludeRegex(
+            "^/.*(\\.map|\\.js|\\.css|\\.ico|\\.svg|\\.png|\\.html|\\.htm)$"));
+    // skip login rest api
+    pac4jConfig.addMatcher("api", new PathMatcher().excludeRegex("^/api/auth/login$"));
+    this.pac4jConfig = pac4jConfig;
+
+    return pac4jConfig;
+  }
+
+  @Override
+  public String getClient(HttpServletRequest httpServletRequest) {
+    return "HeaderClient";
+  }
+
+  @Override
+  public Optional<JwtProfile> perform(HttpServletRequest hsRequest, HttpServletResponse hsResponse) {
+    JEEContext context = new JEEContext(hsRequest, hsResponse, CommonFilter.SESSION_STORE);
+    UserProfile profile = CommonFilter.SECURITY_LOGIC.perform(
+        context,
+        pac4jConfig,
+        (JEEContext ctx, Collection<UserProfile> profiles, Object... parameters) -> {
+          if (profiles.isEmpty()) {
+            LOG.warn("No profiles found with default auth.");
+            return null;
+          } else {
+            return profiles.iterator().next();
+          }
+        },
+        CommonFilter.DEFAULT_HTTP_ACTION_ADAPTER,
+        getClient(hsRequest), DEFAULT_AUTHORIZER, "static,api", null);
+    return Optional.ofNullable((JwtProfile) profile);
+  }
+
+  @Override
+  public Optional<JwtProfile> getProfile(HttpServletRequest hsRequest, HttpServletResponse hsResponse) {
+    JEEContext context = new JEEContext(hsRequest, hsResponse, CommonFilter.SESSION_STORE);
+    ProfileManager<JwtProfile> manager = new ProfileManager<>(context);
+    return manager.get(true);
+  }
+}
diff --git a/submarine-server/server-core/src/test/java/org/apache/submarine/server/security/MockHttpServletRequest.java b/submarine-server/server-core/src/test/java/org/apache/submarine/server/security/MockHttpServletRequest.java
new file mode 100644
index 0000000..49d8e04
--- /dev/null
+++ b/submarine-server/server-core/src/test/java/org/apache/submarine/server/security/MockHttpServletRequest.java
@@ -0,0 +1,409 @@
+/*
+ * 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.submarine.server.security;
+
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpUpgradeHandler;
+import javax.servlet.http.Part;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.Principal;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+public class MockHttpServletRequest implements HttpServletRequest {
+
+  @Override
+  public String getAuthType() {
+    return null;
+  }
+
+  @Override
+  public Cookie[] getCookies() {
+    return new Cookie[0];
+  }
+
+  @Override
+  public long getDateHeader(String name) {
+    return 0;
+  }
+
+  private final HashMap<String, String> headers = new HashMap<>();
+
+  @Override
+  public String getHeader(String name) {
+    return headers.get(name);
+  }
+
+  @Override
+  public Enumeration<String> getHeaders(String name) {
+    return Collections.enumeration(Collections.singleton(headers.get(name)));
+  }
+
+  public void setHeader(String name, String value) {
+    headers.put(name, value);
+  }
+
+  @Override
+  public Enumeration<String> getHeaderNames() {
+    return Collections.enumeration(headers.keySet());
+  }
+
+  @Override
+  public int getIntHeader(String name) {
+    return 0;
+  }
+
+  @Override
+  public String getMethod() {
+    return null;
+  }
+
+  @Override
+  public String getPathInfo() {
+    return null;
+  }
+
+  @Override
+  public String getPathTranslated() {
+    return null;
+  }
+
+  @Override
+  public String getContextPath() {
+    return null;
+  }
+
+  @Override
+  public String getQueryString() {
+    return null;
+  }
+
+  @Override
+  public String getRemoteUser() {
+    return null;
+  }
+
+  @Override
+  public boolean isUserInRole(String role) {
+    return false;
+  }
+
+  @Override
+  public Principal getUserPrincipal() {
+    return null;
+  }
+
+  @Override
+  public String getRequestedSessionId() {
+    return null;
+  }
+
+  @Override
+  public String getRequestURI() {
+    return null;
+  }
+
+  private StringBuffer requestUrl;
+
+  @Override
+  public StringBuffer getRequestURL() {
+    return requestUrl;
+  }
+
+  public void setRequestURL(StringBuffer requestUrl) {
+    this.requestUrl = requestUrl;
+  }
+
+  @Override
+  public String getServletPath() {
+    return null;
+  }
+
+  @Override
+  public HttpSession getSession(boolean create) {
+    return null;
+  }
+
+  @Override
+  public HttpSession getSession() {
+    return null;
+  }
+
+  @Override
+  public String changeSessionId() {
+    return null;
+  }
+
+  @Override
+  public boolean isRequestedSessionIdValid() {
+    return false;
+  }
+
+  @Override
+  public boolean isRequestedSessionIdFromCookie() {
+    return false;
+  }
+
+  @Override
+  public boolean isRequestedSessionIdFromURL() {
+    return false;
+  }
+
+  @Override
+  public boolean isRequestedSessionIdFromUrl() {
+    return false;
+  }
+
+  @Override
+  public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
+    return false;
+  }
+
+  @Override
+  public void login(String username, String password) throws ServletException {
+
+  }
+
+  @Override
+  public void logout() throws ServletException {
+
+  }
+
+  @Override
+  public Collection<Part> getParts() throws IOException, ServletException {
+    return null;
+  }
+
+  @Override
+  public Part getPart(String name) throws IOException, ServletException {
+    return null;
+  }
+
+  @Override
+  public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass)
+      throws IOException, ServletException {
+    return null;
+  }
+
+  @Override
+  public String getCharacterEncoding() {
+    return null;
+  }
+
+  @Override
+  public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
+
+  }
+
+  @Override
+  public int getContentLength() {
+    return 0;
+  }
+
+  @Override
+  public long getContentLengthLong() {
+    return 0;
+  }
+
+  @Override
+  public String getContentType() {
+    return null;
+  }
+
+  @Override
+  public ServletInputStream getInputStream() throws IOException {
+    return null;
+  }
+
+  @Override
+  public String getParameter(String name) {
+    return null;
+  }
+
+  @Override
+  public Enumeration<String> getParameterNames() {
+    return null;
+  }
+
+  @Override
+  public String[] getParameterValues(String name) {
+    return new String[0];
+  }
+
+  @Override
+  public Map<String, String[]> getParameterMap() {
+    return null;
+  }
+
+  @Override
+  public String getProtocol() {
+    return null;
+  }
+
+  @Override
+  public String getScheme() {
+    return null;
+  }
+
+  @Override
+  public String getServerName() {
+    return null;
+  }
+
+  @Override
+  public int getServerPort() {
+    return 0;
+  }
+
+  @Override
+  public BufferedReader getReader() throws IOException {
+    return null;
+  }
+
+  @Override
+  public String getRemoteAddr() {
+    return null;
+  }
+
+  @Override
+  public String getRemoteHost() {
+    return null;
+  }
+
+  private Map<String, Object> attributes = new HashMap<>();
+
+  @Override
+  public Object getAttribute(String name) {
+    return attributes.get(name);
+  }
+
+  @Override
+  public Enumeration<String> getAttributeNames() {
+    return Collections.enumeration(attributes.keySet());
+  }
+
+  @Override
+  public void setAttribute(String name, Object o) {
+    attributes.put(name, o);
+  }
+
+  @Override
+  public void removeAttribute(String name) {
+    attributes.remove(name);
+  }
+
+  @Override
+  public Locale getLocale() {
+    return null;
+  }
+
+  @Override
+  public Enumeration<Locale> getLocales() {
+    return null;
+  }
+
+  @Override
+  public boolean isSecure() {
+    return false;
+  }
+
+  @Override
+  public RequestDispatcher getRequestDispatcher(String path) {
+    return null;
+  }
+
+  @Override
+  public String getRealPath(String path) {
+    return null;
+  }
+
+  @Override
+  public int getRemotePort() {
+    return 0;
+  }
+
+  @Override
+  public String getLocalName() {
+    return null;
+  }
+
+  @Override
+  public String getLocalAddr() {
+    return null;
+  }
+
+  @Override
+  public int getLocalPort() {
+    return 0;
+  }
+
+  @Override
+  public ServletContext getServletContext() {
+    return null;
+  }
+
+  @Override
+  public AsyncContext startAsync() throws IllegalStateException {
+    return null;
+  }
+
+  @Override
+  public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse)
+      throws IllegalStateException {
+    return null;
+  }
+
+  @Override
+  public boolean isAsyncStarted() {
+    return false;
+  }
+
+  @Override
+  public boolean isAsyncSupported() {
+    return false;
+  }
+
+  @Override
+  public AsyncContext getAsyncContext() {
+    return null;
+  }
+
+  @Override
+  public DispatcherType getDispatcherType() {
+    return null;
+  }
+}
diff --git a/submarine-server/server-core/src/test/java/org/apache/submarine/server/security/SubmarineAuthSimpleTest.java b/submarine-server/server-core/src/test/java/org/apache/submarine/server/security/SubmarineAuthSimpleTest.java
new file mode 100644
index 0000000..b86b7b5
--- /dev/null
+++ b/submarine-server/server-core/src/test/java/org/apache/submarine/server/security/SubmarineAuthSimpleTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.submarine.server.security;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+import org.apache.submarine.commons.utils.SubmarineConfVars;
+import org.apache.submarine.commons.utils.SubmarineConfiguration;
+import org.apache.submarine.server.api.environment.EnvironmentId;
+import org.apache.submarine.server.database.workbench.entity.SysUserEntity;
+import org.apache.submarine.server.rest.workbench.LoginRestApi;
+import org.apache.submarine.server.rest.workbench.SysUserRestApi;
+import org.apache.submarine.server.security.simple.SimpleFilter;
+import org.apache.submarine.server.utils.gson.EnvironmentIdDeserializer;
+import org.apache.submarine.server.utils.gson.EnvironmentIdSerializer;
+import org.apache.submarine.server.utils.response.JsonResponse;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.pac4j.core.config.Config;
+import org.pac4j.core.util.Pac4jConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Type;
+import java.util.Optional;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class SubmarineAuthSimpleTest {
+
+  private static final SubmarineConfiguration conf = SubmarineConfiguration.getInstance();
+
+  private static final GsonBuilder gsonBuilder = new GsonBuilder()
+          .registerTypeAdapter(EnvironmentId.class, new EnvironmentIdSerializer())
+          .registerTypeAdapter(EnvironmentId.class, new EnvironmentIdDeserializer());
+  private static final Gson gson = gsonBuilder.setDateFormat("yyyy-MM-dd HH:mm:ss").create();
+
+  private static final Logger LOG = LoggerFactory.getLogger(SubmarineAuthSimpleTest.class);
+
+  private static LoginRestApi loginRestApi;
+  private static SysUserRestApi sysUserRestApi;
+
+  @Before
+  public void before() {
+    conf.updateConfiguration("submarine.auth.type", "simple");
+    conf.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/submarine_test?" +
+            "useUnicode=true&" +
+            "characterEncoding=UTF-8&" +
+            "autoReconnect=true&" +
+            "failOverReadOnly=false&" +
+            "zeroDateTimeBehavior=convertToNull&" +
+            "useSSL=false");
+    conf.setJdbcUserName("submarine_test");
+    conf.setJdbcPassword("password_test");
+    loginRestApi = new LoginRestApi();
+    // add a test user
+    sysUserRestApi = new SysUserRestApi();
+    SysUserEntity user = new SysUserEntity();
+    user.setUserName("test");
+    user.setRealName("test");
+    user.setPassword("test");
+    user.setDeleted(0);
+    sysUserRestApi.add(user);
+  }
+
+  @Test
+  public void testSimpleType() throws ServletException, IOException {
+    // test auth type config
+    String authType = conf.getString(SubmarineConfVars.ConfVars.SUBMARINE_AUTH_TYPE);
+    assertEquals(authType, "simple");
+
+    // test provider
+    Optional<SecurityProvider> providerOptional = SecurityFactory.getSecurityProvider();
+    SecurityProvider provider = providerOptional.get();
+    assertNotNull(provider);
+    assertEquals(provider.getFilterClass(), SimpleFilter.class);
+    Config config = provider.getConfig();
+    assertTrue(config.getClients().findClient("headerClient").isPresent());
+
+    // test login api
+    String testUsrJson = "{\"username\":\"test\",\"password\":\"test\"}";
+    Response loginResp = loginRestApi.login(testUsrJson);
+    assertEquals(loginResp.getStatus(), Response.Status.OK.getStatusCode());
+    String entity = (String) loginResp.getEntity();
+    Type type = new TypeToken<JsonResponse<SysUserEntity>>() { }.getType();
+    JsonResponse<SysUserEntity> jsonResponse = gson.fromJson(entity, type);
+    String token = jsonResponse.getResult().getToken();
+    LOG.info("Get user token: " + token);
+
+    // create filter involved objects
+    // 1. test filter
+    SimpleFilter filterTest = new SimpleFilter();
+    filterTest.init(null);
+    // 2. filter chain
+    FilterChain mockFilterChain = Mockito.mock(FilterChain.class);
+    // 3. http request
+    MockHttpServletRequest mockRequest = new MockHttpServletRequest();
+    mockRequest.setRequestURL(new StringBuffer("/test/url"));
+    // 4. http response
+    HttpServletResponse mockResponse = Mockito.mock(HttpServletResponse.class);
+    StringWriter out = new StringWriter();
+    PrintWriter printOut = new PrintWriter(out);
+    when(mockResponse.getWriter()).thenReturn(printOut);
+
+    // test no header
+    filterTest.doFilter(mockRequest, mockResponse, mockFilterChain);
+    verify(mockResponse).sendError(HttpServletResponse.SC_UNAUTHORIZED, "The token is not valid.");
+
+    // test header
+    mockRequest.setHeader("Authorization", "Bearer " + token);
+    filterTest.doFilter(mockRequest, mockResponse, mockFilterChain);
+    verify(mockFilterChain).doFilter(mockRequest, mockResponse);
+    assertNotNull(mockRequest.getAttribute(Pac4jConstants.USER_PROFILES));
+  }
+
+}
diff --git a/submarine-server/server-core/src/test/resources/log4j.properties b/submarine-server/server-core/src/test/resources/log4j.properties
new file mode 100644
index 0000000..bef97ca
--- /dev/null
+++ b/submarine-server/server-core/src/test/resources/log4j.properties
@@ -0,0 +1,20 @@
+# Licensed 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. See accompanying LICENSE file.
+log4j.rootLogger = info, stdout
+
+log4j.appender.stdout = org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target = System.out
+log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
+
+log4j.logger.org.apache.submarine = debug
+log4j.logger.org.pac4j = debug
diff --git a/submarine-server/server-database/src/main/java/org/apache/submarine/server/database/workbench/mappers/SysUserMapper.java b/submarine-server/server-database/src/main/java/org/apache/submarine/server/database/workbench/mappers/SysUserMapper.java
index 1528566..b0493fc 100644
--- a/submarine-server/server-database/src/main/java/org/apache/submarine/server/database/workbench/mappers/SysUserMapper.java
+++ b/submarine-server/server-database/src/main/java/org/apache/submarine/server/database/workbench/mappers/SysUserMapper.java
@@ -31,7 +31,11 @@
 
   void add(SysUserEntity sysOrg);
 
-  SysUserEntity getById(String id);
+  SysUserEntity getUserByName(Map<String, String> where);
+
+  void activeUser(String id);
+
+  SysUserEntity getUserByUniqueName(String name);
 
   void updateBy(SysUserEntity sysUser);
 
diff --git a/submarine-server/server-database/src/main/resources/org/apache/submarine/database/mappers/SysUserMapper.xml b/submarine-server/server-database/src/main/resources/org/apache/submarine/database/mappers/SysUserMapper.xml
index f4b6f88..49c4e9e 100644
--- a/submarine-server/server-database/src/main/resources/org/apache/submarine/database/mappers/SysUserMapper.xml
+++ b/submarine-server/server-database/src/main/resources/org/apache/submarine/database/mappers/SysUserMapper.xml
@@ -50,7 +50,15 @@
   </select>
 
   <select id="login" parameterType="java.util.Map" resultMap="resultMap">
-    SELECT * FROM sys_user WHERE user_name = #{username} AND password = #{password}
+    SELECT * FROM sys_user WHERE user_name = #{username} AND password = #{password} AND deleted = 0
+  </select>
+
+  <update id="activeUser" parameterType="String">
+    UPDATE sys_user SET delete = 0 where id = #{id}
+  </update>
+
+  <select id="getUserByUniqueName" parameterType="String" resultMap="resultMap">
+    SELECT * FROM sys_user WHERE user_name = #{mapParams.name}
   </select>
 
   <insert id="add" parameterType="org.apache.submarine.server.database.workbench.entity.SysUserEntity">