This is an automated email from the ASF dual-hosted git repository.
guangning pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar-manager.git
The following commit(s) were added to refs/heads/master by this push:
new 4ab8811 Add support for casdoor (#446)
4ab8811 is described below
commit 4ab8811a48ce7d2c8148f765f9cd9b62fbb76bfb
Author: Fabian Bao <[email protected]>
AuthorDate: Wed Apr 13 09:54:09 2022 +0800
Add support for casdoor (#446)
feet: add support for casdoor
---
build.gradle | 1 +
front-end/package.json | 4 +--
front-end/src/api/login.js | 13 +++++++++
front-end/src/lang/en.js | 1 +
front-end/src/lang/zh.js | 1 +
front-end/src/permission.js | 2 +-
front-end/src/router/index.js | 7 ++++-
front-end/src/store/modules/user.js | 18 ++++++++++++
front-end/src/views/callback/index.vue | 18 ++++++++++++
front-end/src/views/login/index.vue | 13 +++++++--
.../pulsar/manager/controller/LoginController.java | 34 ++++++++++++++++++++++
.../manager/interceptor/WebAppConfigurer.java | 1 +
src/main/resources/application.properties | 12 ++++++--
13 files changed, 117 insertions(+), 8 deletions(-)
diff --git a/build.gradle b/build.gradle
index 0ccab9c..9a9dc9b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -148,6 +148,7 @@ dependencies {
compile group: 'org.glassfish.jersey.media', name:
'jersey-media-json-jackson', version: jerseyVersion
compile group: 'org.springframework.boot', name:
'spring-boot-starter-security'
compile group: 'org.springframework.security', name:
'spring-security-config'
+ compile group: 'org.casbin', name: 'casdoor-spring-boot-starter', version:
'1.2.0'
compileOnly group: 'org.projectlombok', name: 'lombok', version:
lombokVersion
compileOnly group: 'org.springframework.boot', name:
'spring-boot-devtools', version: springBootVersion
testCompile group: 'org.springframework.boot', name:
'spring-boot-starter-test', version: springBootVersion
diff --git a/front-end/package.json b/front-end/package.json
index 64225d6..eca0935 100644
--- a/front-end/package.json
+++ b/front-end/package.json
@@ -5,7 +5,7 @@
"author": "<[email protected]>",
"license": "Apache License 2.0",
"scripts": {
- "dev": "cross-env BABEL_ENV=development webpack-dev-server --inline
--progress --config build/webpack.dev.conf.js",
+ "dev": "cross-env BABEL_ENV=development
NODE_OPTIONS=--openssl-legacy-provider webpack-dev-server --inline --progress
--config build/webpack.dev.conf.js",
"build:prod": "cross-env NODE_ENV=production env_config=prod node
build/build.js",
"build:sit": "cross-env NODE_ENV=production env_config=sit node
build/build.js",
"lint": "eslint --ext .js,.vue src",
@@ -35,6 +35,7 @@
},
"dependencies": {
"axios": "0.18.1",
+ "casdoor-js-sdk": "^0.2.5",
"clipboard": "1.7.1",
"codemirror": "5.39.2",
"connect": "3.6.6",
@@ -97,7 +98,6 @@
"request": "^2.88.0",
"rimraf": "2.6.2",
"sass-loader": "7.0.3",
- "script-ext-html-webpack-plugin": "2.0.1",
"script-loader": "0.7.2",
"semver": "5.5.0",
"serve-static": "1.13.2",
diff --git a/front-end/src/api/login.js b/front-end/src/api/login.js
index 0c3ca2e..7bfc6f4 100644
--- a/front-end/src/api/login.js
+++ b/front-end/src/api/login.js
@@ -26,6 +26,19 @@ export function loginByUsername(username, password) {
})
}
+export function loginByCasdoor(code, state) {
+ const data = {
+ code,
+ state
+ }
+ return request({
+ headers: { 'Content-Type': 'application/json' },
+ url: '/pulsar-manager/casdoor',
+ method: 'post',
+ data
+ })
+}
+
export function logout() {
return request({
url: '/pulsar-manager/logout',
diff --git a/front-end/src/lang/en.js b/front-end/src/lang/en.js
index 6e359da..1161a62 100644
--- a/front-end/src/lang/en.js
+++ b/front-end/src/lang/en.js
@@ -104,6 +104,7 @@ export default {
username: 'Username',
password: 'Password',
any: 'any',
+ casdoor: 'Login with casdoor',
thirdparty: 'Or connect with',
thirdpartyTips: 'Can not be simulated on local, so please combine you own
business simulation! ! !'
},
diff --git a/front-end/src/lang/zh.js b/front-end/src/lang/zh.js
index d466f8b..610d2ba 100644
--- a/front-end/src/lang/zh.js
+++ b/front-end/src/lang/zh.js
@@ -104,6 +104,7 @@ export default {
username: 'Username',
password: 'Password',
any: 'any',
+ casdoor: 'Login with casdoor',
thirdparty: 'Or connect with',
thirdpartyTips: 'Can not be simulated on local, so please combine you own
business simulation! ! !'
},
diff --git a/front-end/src/permission.js b/front-end/src/permission.js
index 42b574e..b100d90 100644
--- a/front-end/src/permission.js
+++ b/front-end/src/permission.js
@@ -27,7 +27,7 @@ function hasPermission(roles, permissionRoles) {
return roles.some(role => permissionRoles.indexOf(role) >= 0)
}
-const whiteList = ['/login']// no redirect whitelist
+const whiteList = ['/login', '/callback']// no redirect whitelist
router.beforeEach((to, from, next) => {
NProgress.start() // start progress bar
diff --git a/front-end/src/router/index.js b/front-end/src/router/index.js
index 64f6339..e7be854 100644
--- a/front-end/src/router/index.js
+++ b/front-end/src/router/index.js
@@ -54,6 +54,11 @@ export const constantRouterMap = [
component: () => import('@/views/login/index'),
hidden: true
},
+ {
+ path: '/callback',
+ component: () => import('@/views/callback/index'),
+ hidden: true
+ },
{
path: '/auth-redirect',
component: () => import('@/views/login/authredirect'),
@@ -72,7 +77,7 @@ export const constantRouterMap = [
]
export default new Router({
- // mode: 'history', // require service support
+ mode: 'history', // require service support
scrollBehavior: () => ({ y: 0 }),
routes: constantRouterMap
})
diff --git a/front-end/src/store/modules/user.js
b/front-end/src/store/modules/user.js
index b2acd3c..9b2dc5d 100644
--- a/front-end/src/store/modules/user.js
+++ b/front-end/src/store/modules/user.js
@@ -19,6 +19,7 @@ import { removeCsrfToken } from '@/utils/csrfToken'
import { Message } from 'element-ui'
import { setTenant, removeTenant } from '../../utils/tenant'
import { getUserInfo } from '@/api/users'
+import { loginByCasdoor } from '../../api/login'
const user = {
state: {
@@ -86,6 +87,23 @@ const user = {
})
},
+ LoginByCasdoor({ commit }, code, state) {
+ return new Promise((resolve, reject) => {
+ loginByCasdoor(code, state).then(response => {
+ if (response.data.hasOwnProperty('error') &&
response.data.error.length >= 0) {
+ reject('login error')
+ }
+ commit('SET_TOKEN', response.headers.token)
+ setToken(response.headers.token)
+ setName(response.headers.username)
+ setTenant(response.headers.tenant)
+ resolve()
+ }).catch(error => {
+ reject(error)
+ })
+ })
+ },
+
// 获取用户信息
GetUserInfo({ commit, state }) {
return new Promise((resolve, reject) => {
diff --git a/front-end/src/views/callback/index.vue
b/front-end/src/views/callback/index.vue
new file mode 100644
index 0000000..7e1068e
--- /dev/null
+++ b/front-end/src/views/callback/index.vue
@@ -0,0 +1,18 @@
+<script>
+export default {
+ name: 'Index',
+ watch: {
+ $route: {
+ handler: function(route) {
+ this.$store.dispatch('LoginByCasdoor', route.query.code,
route.query.state).then(() => {
+ this.$router.push({ path: '/' })
+ }).catch(() => {
+ console.log('login error!!')
+ })
+ },
+ immediate: true
+ }
+
+ }
+}
+</script>
diff --git a/front-end/src/views/login/index.vue
b/front-end/src/views/login/index.vue
index f4b79c3..cf0aa59 100644
--- a/front-end/src/views/login/index.vue
+++ b/front-end/src/views/login/index.vue
@@ -53,9 +53,10 @@
</el-form-item>
<el-button :loading="loading" type="primary"
style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">{{
$t('login.logIn') }}</el-button>
+ <el-button :loading="loading" type="primary"
style="width:100%;margin-left:0;" @click="loginWithCasdoor">{{
$t('login.casdoor') }}</el-button>
<!-- <el-button class="thirdparty-button" type="primary"
@click="showDialog=true">
- Or connect with
- </el-button> -->
+ Or connect with
+ </el-button> -->
</el-form>
<el-dialog :title="$t('login.thirdparty')" :visible.sync="showDialog"
append-to-body>
@@ -180,6 +181,14 @@ export default {
getCsrfToken().then(response => {
setCsrfToken(response.headers['x-csrf-token'])
})
+ },
+ loginWithCasdoor() {
+ window.location.href = 'http://localhost:7001/login/oauth/authorize' +
+ '?client_id=6ba06c1e1a30929fdda7' +
+ '&response_type=code' +
+ '&redirect_uri=http://localhost:9527/callback' +
+ '&scope=read' +
+ '&state=pulsar'
}
}
}
diff --git
a/src/main/java/org/apache/pulsar/manager/controller/LoginController.java
b/src/main/java/org/apache/pulsar/manager/controller/LoginController.java
index 7e199ee..febf877 100644
--- a/src/main/java/org/apache/pulsar/manager/controller/LoginController.java
+++ b/src/main/java/org/apache/pulsar/manager/controller/LoginController.java
@@ -30,6 +30,10 @@ import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.apache.pulsar.manager.utils.ResourceType;
+import org.casbin.casdoor.entity.CasdoorUser;
+import org.casbin.casdoor.service.CasdoorAuthService;
+import org.casbin.casdoor.service.CasdoorResourceService;
+import org.casbin.casdoor.service.CasdoorUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
@@ -81,6 +85,9 @@ public class LoginController {
@Autowired
private RolesRepository rolesRepository;
+ @Autowired
+ private CasdoorAuthService casdoorAuthService;
+
@Autowired
private RoleBindingRepository roleBindingRepository;
@@ -180,4 +187,31 @@ public class LoginController {
jwtService.removeToken(request.getSession().getId());
return ResponseEntity.ok(result);
}
+
+ @ApiOperation(value = "Logout pulsar manager")
+ @ApiResponses({
+ @ApiResponse(code = 200, message = "ok"),
+ @ApiResponse(code = 500, message = "Internal server error")
+ })
+ @RequestMapping(value = "/casdoor", method = RequestMethod.POST)
+ public ResponseEntity<Map<String, Object>> callback(
+ @RequestBody Map<String, String> body) {
+ Map<String, Object> result = Maps.newHashMap();
+ String code = body.get("code");
+ String state = body.get("state");
+ String token = casdoorAuthService.getOAuthToken(code, state);
+ if(!token.startsWith("error")){
+ result.put("error", token.substring(7));
+ return ResponseEntity.ok(result);
+ }
+ result.put("login", "success");
+ HttpHeaders headers = new HttpHeaders();
+ HttpServletRequest request = ((ServletRequestAttributes)
RequestContextHolder.getRequestAttributes()).getRequest();
+ String jwtToken = jwtService.toToken(account + "-" + password);
+ jwtService.setToken(request.getSession().getId(), jwtToken);
+ headers.add("token", jwtToken);
+ headers.add("tenant","pulsar");
+ headers.add("username", "pulsar");
+ return new ResponseEntity<>(result, headers, HttpStatus.OK);
+ }
}
diff --git
a/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
b/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
index ddfd79f..26adffc 100644
--- a/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
+++ b/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
@@ -34,6 +34,7 @@ public class WebAppConfigurer implements WebMvcConfigurer {
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(adminHandlerInterceptor).addPathPatterns("/**")
.excludePathPatterns("/pulsar-manager/login")
+ .excludePathPatterns("/pulsar-manager/casdoor")
.excludePathPatterns("/pulsar-manager/users/superuser")
.excludePathPatterns("/pulsar-manager/csrf-token")
.excludePathPatterns("/pulsar-manager/third-party-login/**")
diff --git a/src/main/resources/application.properties
b/src/main/resources/application.properties
index ba598eb..2781e4e 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -88,7 +88,7 @@ jwt.sessionTime=2592000
pulsar-manager.account=pulsar
pulsar-manager.password=pulsar
# If true, the database is used for user management
-user.management.enable=true
+user.management.enable=false
# Optional -> SECRET, PRIVATE, default -> PRIVATE, empty -> disable auth
# SECRET mode -> bin/pulsar tokens create --secret-key
file:///path/to/my-secret.key --subject test-user
@@ -154,5 +154,13 @@ tls.pulsar.admin.ca-certs=ca-client-path
# support peek message, default false
pulsar.peek.message=false
-# swagger configration
+# swagger configuration
swagger.enabled=false
+
+# casdoor configuration
+casdoor.endpoint = http://localhost:8000
+casdoor.clientId = 6ba06c1e1a30929fdda7
+casdoor.clientSecret = df92bbf913225ebbae9af7ba8d41fe19507eb079
+casdoor.jwtPublicKey = -----BEGIN
CERTIFICATE-----\nMIIE+TCCAuGgAwIBAgIDAeJAMA0GCSqGSIb3DQEBCwUAMDYxHTAbBgNVBAoTFENh\nc2Rvb3IgT3JnYW5pemF0aW9uMRUwEwYDVQQDEwxDYXNkb29yIENlcnQwHhcNMjEx\nMDE1MDgxMTUyWhcNNDExMDE1MDgxMTUyWjA2MR0wGwYDVQQKExRDYXNkb29yIE9y\nZ2FuaXphdGlvbjEVMBMGA1UEAxMMQ2FzZG9vciBDZXJ0MIICIjANBgkqhkiG9w0B\nAQEFAAOCAg8AMIICCgKCAgEAsInpb5E1/ym0f1RfSDSSE8IR7y+lw+RJjI74e5ej\nrq4b8zMYk7HeHCyZr/hmNEwEVXnhXu1P0mBeQ5ypp/QGo8vgEmjAETNmzkI1NjOQ\nCjCYwUrasO/f/MnI1C0j13vx6mV1kHZjSrKsMhYY1vax
[...]
+casdoor.organizationName = built-in
+casdoor.applicationName = pulsar