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 2022/11/14 02:40:47 UTC
[shardingsphere-elasticjob-ui] branch master updated: feat: add support for Casdoor authentication (#174)
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-ui.git
The following commit(s) were added to refs/heads/master by this push:
new 764d1c2 feat: add support for Casdoor authentication (#174)
764d1c2 is described below
commit 764d1c2eb672eb0673b96fccbc537962b1bd2a4f
Author: jakiuncle <88...@users.noreply.github.com>
AuthorDate: Mon Nov 14 10:40:41 2022 +0800
feat: add support for Casdoor authentication (#174)
* feat: add support for Casdoor authentication
---
.../pom.xml | 5 ++
.../lite/ui/security/AuthenticationFilter.java | 82 ++++++++++++++++++----
.../elasticjob/lite/ui/security/OAuthCode.java} | 19 +++--
.../src/main/resources/application.properties | 36 ++++++++++
.../src/views/login/api.js | 4 +-
.../src/views/login/{api.js => casdoor.js} | 23 +++++-
.../src/views/login/index.vue | 18 +++++
7 files changed, 167 insertions(+), 20 deletions(-)
diff --git a/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/pom.xml b/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/pom.xml
index 0acf54a..5f57dce 100644
--- a/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/pom.xml
+++ b/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/pom.xml
@@ -79,6 +79,11 @@
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.casbin</groupId>
+ <artifactId>casdoor-spring-boot-starter</artifactId>
+ <version>1.3.0</version>
+ </dependency>
</dependencies>
<build>
diff --git a/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/lite/ui/security/AuthenticationFilter.java b/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/lite/ui/security/AuthenticationFilter.java
index 98541d5..c65de49 100644
--- a/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/lite/ui/security/AuthenticationFilter.java
+++ b/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/lite/ui/security/AuthenticationFilter.java
@@ -21,13 +21,13 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Strings;
import lombok.Setter;
import org.apache.shardingsphere.elasticjob.lite.ui.web.response.ResponseResultUtil;
+import org.casbin.casdoor.config.CasdoorConfiguration;
+import org.casbin.casdoor.entity.CasdoorUser;
+import org.casbin.casdoor.service.CasdoorAuthService;
+import org.springframework.context.ApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
-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.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@@ -40,14 +40,25 @@ import java.util.Map;
public final class AuthenticationFilter implements Filter {
private static final String LOGIN_URI = "/api/login";
-
+
+ private static final String CASDOOR_LOGIN_URL = "/api/casdoor-login-url";
+
+ private static final String CASDOOR_LOGIN = "/api/casdoor-login";
private final ObjectMapper objectMapper = new ObjectMapper();
@Setter
private UserAuthenticationService userAuthenticationService;
-
+
+ private CasdoorAuthService casdoorAuthService;
+
+ private String loginMethod = "default";
+
@Override
public void init(final FilterConfig filterConfig) {
+ ServletContext servletContext = filterConfig.getServletContext();
+ ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);
+ CasdoorConfiguration config = ctx.getBean(CasdoorConfiguration.class);
+ casdoorAuthService = new CasdoorAuthService(config);
}
@Override
@@ -58,11 +69,26 @@ public final class AuthenticationFilter implements Filter {
handleLogin(httpRequest, httpResponse);
return;
}
- String accessToken = httpRequest.getHeader("Access-Token");
- if (Strings.isNullOrEmpty(accessToken) || !userAuthenticationService.isValidToken(accessToken)) {
- respondWithUnauthorized(httpResponse);
+ if (CASDOOR_LOGIN_URL.equals(httpRequest.getRequestURI())) {
+ handleCasdoorLoginUrl(httpRequest, httpResponse);
+ return;
+ }
+ if (CASDOOR_LOGIN.equals(httpRequest.getRequestURI())) {
+ handleCasdoorLogin(httpRequest, httpResponse);
return;
}
+ String accessToken = httpRequest.getHeader("Access-Token");
+ if(loginMethod == "default"){
+ if (Strings.isNullOrEmpty(accessToken) || !userAuthenticationService.isValidToken(accessToken)) {
+ respondWithUnauthorized(httpResponse);
+ return;
+ }
+ }else{
+ if(casdoorAuthService.parseJwtToken(accessToken) == null){
+ respondWithUnauthorized(httpResponse);
+ return;
+ }
+ }
filterChain.doFilter(httpRequest, httpResponse);
}
@@ -83,12 +109,44 @@ public final class AuthenticationFilter implements Filter {
Map<String, Object> result = new HashMap<>(2, 1);
result.put("username", authenticationResult.getUsername());
result.put("accessToken", userAuthenticationService.getToken(authenticationResult.getUsername()));
+ loginMethod = "default";
objectMapper.writeValue(httpResponse.getWriter(), ResponseResultUtil.build(result));
} catch (IOException e) {
e.printStackTrace();
}
}
-
+
+ private void handleCasdoorLoginUrl(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
+ try {
+ String origin = httpRequest.getParameter("origin");
+ String url = casdoorAuthService.getSigninUrl(origin + "/login/casdoor");
+ httpResponse.setContentType("application/json");
+ httpResponse.setCharacterEncoding("UTF-8");
+ Map<String, Object> result = new HashMap<>(1, 1);
+ result.put("casdoorLoginUrl", url);
+ loginMethod = "casdoor";
+ objectMapper.writeValue(httpResponse.getWriter(), ResponseResultUtil.build(result));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void handleCasdoorLogin(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
+ try {
+ OAuthCode code = objectMapper.readValue(httpRequest.getReader(), OAuthCode.class);
+ String token = casdoorAuthService.getOAuthToken(code.getCode(), code.getState());
+ CasdoorUser user = casdoorAuthService.parseJwtToken(token);
+ httpResponse.setContentType("application/json");
+ httpResponse.setCharacterEncoding("UTF-8");
+ Map<String, Object> result = new HashMap<>(4, 1);
+ result.put("username", user.getName());
+ result.put("accessToken", token);
+ objectMapper.writeValue(httpResponse.getWriter(), ResponseResultUtil.build(result));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
private void respondWithUnauthorized(final HttpServletResponse httpResponse) throws IOException {
httpResponse.setContentType("application/json");
httpResponse.setCharacterEncoding("UTF-8");
diff --git a/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/api.js b/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/lite/ui/security/OAuthCode.java
similarity index 77%
copy from shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/api.js
copy to shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/lite/ui/security/OAuthCode.java
index 26ff819..0336478 100644
--- a/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/api.js
+++ b/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/src/main/java/org/apache/shardingsphere/elasticjob/lite/ui/security/OAuthCode.java
@@ -15,8 +15,19 @@
* limitations under the License.
*/
-import API from '@/utils/api'
+package org.apache.shardingsphere.elasticjob.lite.ui.security;
-export default {
- getLogin: (params = {}) => API.post(`/api/login`, params)
-}
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * OAuth code
+ **/
+@Getter
+@Setter
+public final class OAuthCode {
+
+ private String code;
+
+ private String state;
+}
\ No newline at end of file
diff --git a/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/src/main/resources/application.properties b/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/src/main/resources/application.properties
index e2177b2..b8ce26e 100644
--- a/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/src/main/resources/application.properties
+++ b/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-backend/src/main/resources/application.properties
@@ -29,3 +29,39 @@ spring.jpa.show-sql=false
## Uncomment the following property to allow adding DataSource dynamically.
# dynamic.datasource.allowed-driver-classes={'org.h2.Driver','org.postgresql.Driver'}
+
+casdoor.endpoint=http://localhost:7001
+casdoor.client-id=3ed79fa530645fbd3653
+casdoor.client-secret=54633c82b7796a4332c6976864c6c16bc3b05556
+casdoor.certificate=\
+-----BEGIN CERTIFICATE-----\n\
+MIIE+TCCAuGgAwIBAgIDAeJAMA0GCSqGSIb3DQEBCwUAMDYxHTAbBgNVBAoTFENh\n\
+c2Rvb3IgT3JnYW5pemF0aW9uMRUwEwYDVQQDEwxDYXNkb29yIENlcnQwHhcNMjEx\n\
+MDE1MDgxMTUyWhcNNDExMDE1MDgxMTUyWjA2MR0wGwYDVQQKExRDYXNkb29yIE9y\n\
+Z2FuaXphdGlvbjEVMBMGA1UEAxMMQ2FzZG9vciBDZXJ0MIICIjANBgkqhkiG9w0B\n\
+AQEFAAOCAg8AMIICCgKCAgEAsInpb5E1/ym0f1RfSDSSE8IR7y+lw+RJjI74e5ej\n\
+rq4b8zMYk7HeHCyZr/hmNEwEVXnhXu1P0mBeQ5ypp/QGo8vgEmjAETNmzkI1NjOQ\n\
+CjCYwUrasO/f/MnI1C0j13vx6mV1kHZjSrKsMhYY1vaxTEP3+VB8Hjg3MHFWrb07\n\
+uvFMCJe5W8+0rKErZCKTR8+9VB3janeBz//zQePFVh79bFZate/hLirPK0Go9P1g\n\
+OvwIoC1A3sarHTP4Qm/LQRt0rHqZFybdySpyWAQvhNaDFE7mTstRSBb/wUjNCUBD\n\
+PTSLVjC04WllSf6Nkfx0Z7KvmbPstSj+btvcqsvRAGtvdsB9h62Kptjs1Yn7GAuo\n\
+I3qt/4zoKbiURYxkQJXIvwCQsEftUuk5ew5zuPSlDRLoLByQTLbx0JqLAFNfW3g/\n\
+pzSDjgd/60d6HTmvbZni4SmjdyFhXCDb1Kn7N+xTojnfaNkwep2REV+RMc0fx4Gu\n\
+hRsnLsmkmUDeyIZ9aBL9oj11YEQfM2JZEq+RVtUx+wB4y8K/tD1bcY+IfnG5rBpw\n\
+IDpS262boq4SRSvb3Z7bB0w4ZxvOfJ/1VLoRftjPbLIf0bhfr/AeZMHpIKOXvfz4\n\
+yE+hqzi68wdF0VR9xYc/RbSAf7323OsjYnjjEgInUtRohnRgCpjIk/Mt2Kt84Kb0\n\
+wn8CAwEAAaMQMA4wDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAn2lf\n\
+DKkLX+F1vKRO/5gJ+Plr8P5NKuQkmwH97b8CS2gS1phDyNgIc4/LSdzuf4Awe6ve\n\
+C06lVdWSIis8UPUPdjmT2uMPSNjwLxG3QsrimMURNwFlLTfRem/heJe0Zgur9J1M\n\
+8haawdSdJjH2RgmFoDeE2r8NVRfhbR8KnCO1ddTJKuS1N0/irHz21W4jt4rxzCvl\n\
+2nR42Fybap3O/g2JXMhNNROwZmNjgpsF7XVENCSuFO1jTywLaqjuXCg54IL7XVLG\n\
+omKNNNcc8h1FCeKj/nnbGMhodnFWKDTsJcbNmcOPNHo6ixzqMy/Hqc+mWYv7maAG\n\
+Jtevs3qgMZ8F9Qzr3HpUc6R3ZYYWDY/xxPisuKftOPZgtH979XC4mdf0WPnOBLqL\n\
+2DJ1zaBmjiGJolvb7XNVKcUfDXYw85ZTZQ5b9clI4e+6bmyWqQItlwt+Ati/uFEV\n\
+XzCj70B4lALX6xau1kLEpV9O1GERizYRz5P9NJNA7KoO5AVMp9w0DQTkt+LbXnZE\n\
+HHnWKy8xHQKZF9sR7YBPGLs/Ac6tviv5Ua15OgJ/8dLRZ/veyFfGo2yZsI+hKVU5\n\
+nCCJHBcAyFnm1hdvdwEdH33jDBjNB6ciotJZrf/3VYaIWSalADosHAgMWfXuWP+h\n\
+8XKXmzlxuHbTMQYtZPDgspS5aK+S4Q9wb8RRAYo=\n\
+-----END CERTIFICATE-----
+casdoor.organization-name=built-in
+casdoor.application-name=sharding
\ No newline at end of file
diff --git a/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/api.js b/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/api.js
index 26ff819..eedc934 100644
--- a/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/api.js
+++ b/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/api.js
@@ -18,5 +18,7 @@
import API from '@/utils/api'
export default {
- getLogin: (params = {}) => API.post(`/api/login`, params)
+ getLogin: (params = {}) => API.post(`/api/login`, params),
+ getCasdoorLoginUrl: (params = {}) => API.get(`/api/casdoor-login-url`, params),
+ getCasdoorLogin: (params = {}) => API.post(`/api/casdoor-login`, params)
}
diff --git a/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/api.js b/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/casdoor.js
similarity index 56%
copy from shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/api.js
copy to shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/casdoor.js
index 26ff819..25f561a 100644
--- a/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/api.js
+++ b/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/casdoor.js
@@ -15,8 +15,25 @@
* limitations under the License.
*/
-import API from '@/utils/api'
+import API from './api'
export default {
- getLogin: (params = {}) => API.post(`/api/login`, params)
-}
+ loginByCasdoor: () => {
+ // callback
+ const urlSearchParams = new URLSearchParams(window.location.search)
+ const params = {
+ code: urlSearchParams.get('code'),
+ state: urlSearchParams.get('state')
+ }
+ if (params.code != null && params.state != null) {
+ API.getCasdoorLogin(params).then(res => {
+ const data = res.model
+ const store = window.localStorage
+ store.setItem('Access-Token', data.accessToken)
+ store.setItem('username', data.username)
+ store.setItem('isGuest', data.isGuest)
+ location.href = '/#/registry-center'
+ })
+ }
+ }
+}
\ No newline at end of file
diff --git a/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/index.vue b/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/index.vue
index cd7ebc0..b95cd70 100644
--- a/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/index.vue
+++ b/shardingsphere-elasticjob-lite-ui/shardingsphere-elasticjob-lite-ui-frontend/src/views/login/index.vue
@@ -56,6 +56,14 @@
@click.native.prevent="handleLogin"
>{{ $t("login.btnTxt") }}</el-button>
</el-form-item>
+ <el-form-item class="btn-login">
+ <el-button
+ :loading="loading"
+ type="primary"
+ style="width:100%;"
+ @click.native.prevent="toLoginUrl()"
+ >{{ $t("Login with Casdoor") }}</el-button>
+ </el-form-item>
</el-form>
<s-footer style="position: fixed;bottom: 0;" />
</div>
@@ -64,6 +72,9 @@
<script>
import SFooter from '../../components/Footer/index'
import API from './api'
+import casdoor from './casdoor'
+
+casdoor.loginByCasdoor()
export default {
name: 'Login',
components: {
@@ -106,6 +117,13 @@ export default {
store.setItem('username', data.username)
location.href = '#/registry-center'
})
+ },
+ toLoginUrl() {
+ // redirect to casdoor login page
+ API.getCasdoorLoginUrl({ origin: window.location.origin }).then(res => {
+ const data = res.model
+ window.location.href = data.casdoorLoginUrl
+ })
}
}
}