You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2019/12/11 07:20:31 UTC
[dubbo-admin] branch develop updated: provide a simple login module
(#521)
This is an automated email from the ASF dual-hosted git repository.
liujun pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-admin.git
The following commit(s) were added to refs/heads/develop by this push:
new c69cfe0 provide a simple login module (#521)
c69cfe0 is described below
commit c69cfe0a1f5f8e133e4559c586939d15b35eb1e2
Author: kexianjun <ke...@hotmail.com>
AuthorDate: Wed Dec 11 15:20:21 2019 +0800
provide a simple login module (#521)
---
.../apache/dubbo/admin/annotation/Authority.java | 31 ++--
.../dubbo/admin/config/WebMvcConfiguration.java | 33 ++--
.../dubbo/admin/controller/AccessesController.java | 5 +-
.../controller/ConditionRoutesController.java | 4 +-
.../admin/controller/LoadBalanceController.java | 4 +-
.../admin/controller/ManagementController.java | 3 +-
.../admin/controller/MetricsCollectController.java | 4 +-
.../admin/controller/OverridesController.java | 4 +-
.../dubbo/admin/controller/ServiceController.java | 4 +-
.../admin/controller/ServiceTestController.java | 4 +-
.../admin/controller/TagRoutesController.java | 4 +-
.../dubbo/admin/controller/UserController.java | 96 ++++++++++
.../dubbo/admin/controller/WeightController.java | 4 +-
.../dubbo/admin/interceptor/AuthInterceptor.java | 60 +++++++
.../src/main/resources/application-test.properties | 1 +
.../src/main/resources/application.properties | 2 +
dubbo-admin-ui/src/App.vue | 20 +--
dubbo-admin-ui/src/{App.vue => Index.vue} | 21 ++-
dubbo-admin-ui/src/Login.vue | 100 +++++++++++
dubbo-admin-ui/src/components/http-common.js | 12 +-
dubbo-admin-ui/src/components/public/Toolbar.vue | 14 +-
dubbo-admin-ui/src/lang/en.js | 5 +-
dubbo-admin-ui/src/lang/zh.js | 5 +-
dubbo-admin-ui/src/main.js | 15 ++
dubbo-admin-ui/src/router/index.js | 195 ++++++++++++++-------
25 files changed, 504 insertions(+), 146 deletions(-)
diff --git a/dubbo-admin-ui/src/components/http-common.js b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/annotation/Authority.java
similarity index 56%
copy from dubbo-admin-ui/src/components/http-common.js
copy to dubbo-admin-server/src/main/java/org/apache/dubbo/admin/annotation/Authority.java
index 3421e56..1e353ef 100644
--- a/dubbo-admin-ui/src/components/http-common.js
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/annotation/Authority.java
@@ -14,24 +14,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import axios from 'axios'
-import Vue from 'vue'
-import HttpStatus from 'http-status'
+package org.apache.dubbo.admin.annotation;
-let instance = axios.create({
- baseURL: '/api/dev'
-})
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
-instance.interceptors.response.use((response) => {
- return response
-}, (error) => {
- if (error.message.indexOf('Network Error') >= 0) {
- Vue.prototype.$notify.error('Network error, please check your network settings!')
- } else if (error.response.status === HttpStatus.UNAUTHORIZED) {
- // TODO jump to url
- } else if (error.response.status >= HttpStatus.BAD_REQUEST) {
- Vue.prototype.$notify.error(error.response.data.message)
- }
-})
+@Inherited
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
-export const AXIOS = instance
+public @interface Authority {
+
+ boolean needLogin() default false;
+}
\ No newline at end of file
diff --git a/dubbo-admin-ui/src/components/http-common.js b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/WebMvcConfiguration.java
similarity index 54%
copy from dubbo-admin-ui/src/components/http-common.js
copy to dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/WebMvcConfiguration.java
index 3421e56..cacadda 100644
--- a/dubbo-admin-ui/src/components/http-common.js
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/WebMvcConfiguration.java
@@ -14,24 +14,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import axios from 'axios'
-import Vue from 'vue'
-import HttpStatus from 'http-status'
+package org.apache.dubbo.admin.config;
-let instance = axios.create({
- baseURL: '/api/dev'
-})
+import org.apache.dubbo.admin.interceptor.AuthInterceptor;
-instance.interceptors.response.use((response) => {
- return response
-}, (error) => {
- if (error.message.indexOf('Network Error') >= 0) {
- Vue.prototype.$notify.error('Network error, please check your network settings!')
- } else if (error.response.status === HttpStatus.UNAUTHORIZED) {
- // TODO jump to url
- } else if (error.response.status >= HttpStatus.BAD_REQUEST) {
- Vue.prototype.$notify.error(error.response.data.message)
- }
-})
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-export const AXIOS = instance
+@Configuration
+public class WebMvcConfiguration implements WebMvcConfigurer {
+ @Autowired
+ private AuthInterceptor interceptor;
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(interceptor).addPathPatterns("/**");
+ }
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/AccessesController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/AccessesController.java
index 3510e54..00e7e7d 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/AccessesController.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/AccessesController.java
@@ -16,7 +16,7 @@
*/
package org.apache.dubbo.admin.controller;
-import org.apache.commons.lang3.StringUtils;
+import org.apache.dubbo.admin.annotation.Authority;
import org.apache.dubbo.admin.common.exception.ParamValidationException;
import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
import org.apache.dubbo.admin.common.exception.VersionValidationException;
@@ -27,6 +27,8 @@ import org.apache.dubbo.admin.service.ProviderService;
import org.apache.dubbo.admin.service.RouteService;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
+
+import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PathVariable;
@@ -41,6 +43,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+@Authority(needLogin = true)
@RestController
@RequestMapping("/api/{env}/rules/access")
public class AccessesController {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ConditionRoutesController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ConditionRoutesController.java
index 8486d3e..7f5d8af 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ConditionRoutesController.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ConditionRoutesController.java
@@ -18,6 +18,8 @@
package org.apache.dubbo.admin.controller;
import org.apache.commons.lang3.StringUtils;
+
+import org.apache.dubbo.admin.annotation.Authority;
import org.apache.dubbo.admin.common.exception.ParamValidationException;
import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
import org.apache.dubbo.admin.common.exception.VersionValidationException;
@@ -37,7 +39,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
-
+@Authority(needLogin = true)
@RestController
@RequestMapping("/api/{env}/rules/route/condition")
public class ConditionRoutesController {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/LoadBalanceController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/LoadBalanceController.java
index 3daad1f..d0f525e 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/LoadBalanceController.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/LoadBalanceController.java
@@ -18,6 +18,8 @@
package org.apache.dubbo.admin.controller;
import org.apache.commons.lang3.StringUtils;
+
+import org.apache.dubbo.admin.annotation.Authority;
import org.apache.dubbo.admin.common.exception.ParamValidationException;
import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
import org.apache.dubbo.admin.common.exception.VersionValidationException;
@@ -38,7 +40,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
-
+@Authority(needLogin = true)
@RestController
@RequestMapping("/api/{env}/rules/balancing")
public class LoadBalanceController {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ManagementController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ManagementController.java
index b12c689..896dae7 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ManagementController.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ManagementController.java
@@ -17,6 +17,7 @@
package org.apache.dubbo.admin.controller;
+import org.apache.dubbo.admin.annotation.Authority;
import org.apache.dubbo.admin.common.exception.ParamValidationException;
import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
import org.apache.dubbo.admin.common.util.Constants;
@@ -37,7 +38,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
-
+@Authority(needLogin = true)
@RestController
@RequestMapping("/api/{env}/manage")
public class ManagementController {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MetricsCollectController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MetricsCollectController.java
index 9c061a2..6acc0af 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MetricsCollectController.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MetricsCollectController.java
@@ -19,6 +19,8 @@ package org.apache.dubbo.admin.controller;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
+
+import org.apache.dubbo.admin.annotation.Authority;
import org.apache.dubbo.admin.common.util.Constants;
import org.apache.dubbo.admin.common.util.Tool;
import org.apache.dubbo.admin.model.domain.Consumer;
@@ -42,7 +44,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
+@Authority(needLogin = true)
@RestController
@RequestMapping("/api/{env}/metrics")
public class MetricsCollectController {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/OverridesController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/OverridesController.java
index c50ae01..39667d9 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/OverridesController.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/OverridesController.java
@@ -18,6 +18,8 @@
package org.apache.dubbo.admin.controller;
import org.apache.commons.lang3.StringUtils;
+
+import org.apache.dubbo.admin.annotation.Authority;
import org.apache.dubbo.admin.common.exception.ParamValidationException;
import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
import org.apache.dubbo.admin.common.exception.VersionValidationException;
@@ -37,7 +39,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
-
+@Authority(needLogin = true)
@RestController
@RequestMapping("/api/{env}/rules/override")
public class OverridesController {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
index 66a05b8..64f19a3 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
@@ -18,6 +18,8 @@
package org.apache.dubbo.admin.controller;
import com.google.gson.Gson;
+
+import org.apache.dubbo.admin.annotation.Authority;
import org.apache.dubbo.admin.common.util.Constants;
import org.apache.dubbo.admin.common.util.Tool;
import org.apache.dubbo.admin.model.domain.Consumer;
@@ -42,7 +44,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
-
+@Authority(needLogin = true)
@RestController
@RequestMapping("/api/{env}")
public class ServiceController {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java
index 9fc946b..cc8b608 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java
@@ -19,6 +19,8 @@ package org.apache.dubbo.admin.controller;
import com.google.gson.Gson;
import org.apache.dubbo.admin.common.util.Constants;
+
+import org.apache.dubbo.admin.annotation.Authority;
import org.apache.dubbo.admin.common.util.ConvertUtil;
import org.apache.dubbo.admin.common.util.ServiceTestUtil;
import org.apache.dubbo.admin.model.domain.MethodMetadata;
@@ -37,7 +39,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
-
+@Authority(needLogin = true)
@RestController
@RequestMapping("/api/{env}/test")
public class ServiceTestController {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/TagRoutesController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/TagRoutesController.java
index f3c88ec..e6b8318 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/TagRoutesController.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/TagRoutesController.java
@@ -18,6 +18,8 @@
package org.apache.dubbo.admin.controller;
import org.apache.commons.lang3.StringUtils;
+
+import org.apache.dubbo.admin.annotation.Authority;
import org.apache.dubbo.admin.common.exception.ParamValidationException;
import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
import org.apache.dubbo.admin.common.exception.VersionValidationException;
@@ -37,7 +39,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
-
+@Authority(needLogin = true)
@RestController
@RequestMapping("/api/{env}/rules/route/tag")
public class TagRoutesController {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/UserController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/UserController.java
new file mode 100644
index 0000000..4cfb3f1
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/UserController.java
@@ -0,0 +1,96 @@
+/*
+ * 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.dubbo.admin.controller;
+
+import org.apache.dubbo.admin.annotation.Authority;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+@RestController
+@RequestMapping("/api/{env}/user")
+public class UserController {
+ public static Map<String /*token*/, User /*user info*/> tokenMap = new ConcurrentHashMap<>();
+
+ @Value("${admin.root.user.name:}")
+ private String rootUserName;
+ @Value("${admin.root.user.password:}")
+ private String rootUserPassword;
+
+ @RequestMapping(value = "/login", method = RequestMethod.GET)
+ public String login(@RequestParam String userName, @RequestParam String password) {
+ if (StringUtils.isBlank(rootUserName) || (rootUserName.equals(userName) && rootUserPassword.equals(password))) {
+ UUID uuid = UUID.randomUUID();
+ String token = uuid.toString();
+ User user = new User();
+ user.setUserName(userName);
+ user.setLastUpdateTime(System.currentTimeMillis());
+ tokenMap.put(token, user);
+ return token;
+ }
+ return null;
+ }
+
+ @Authority(needLogin = true)
+ @RequestMapping(value = "/logout", method = RequestMethod.DELETE)
+ public boolean logout() {
+ HttpServletRequest request =
+ ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
+ String token = request.getHeader("Authorization");
+ return null != tokenMap.remove(token);
+ }
+
+ @Scheduled(cron= "0 5 * * * ?")
+ public void clearExpiredToken() {
+ tokenMap.entrySet().removeIf(entry -> entry.getValue() == null || System.currentTimeMillis() - entry.getValue().getLastUpdateTime() > 1000 * 60 * 15);
+ }
+
+ public static class User {
+ private String userName;
+ private long lastUpdateTime;
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public long getLastUpdateTime() {
+ return lastUpdateTime;
+ }
+
+ public void setLastUpdateTime(long lastUpdateTime) {
+ this.lastUpdateTime = lastUpdateTime;
+ }
+ }
+
+}
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/WeightController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/WeightController.java
index 3333e90..d6cbc4c 100644
--- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/WeightController.java
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/WeightController.java
@@ -18,6 +18,8 @@
package org.apache.dubbo.admin.controller;
import org.apache.commons.lang3.StringUtils;
+
+import org.apache.dubbo.admin.annotation.Authority;
import org.apache.dubbo.admin.common.exception.ParamValidationException;
import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
import org.apache.dubbo.admin.common.exception.VersionValidationException;
@@ -37,7 +39,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
-
+@Authority(needLogin = true)
@RestController
@RequestMapping("/api/{env}/rules/weight")
public class WeightController {
diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/interceptor/AuthInterceptor.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/interceptor/AuthInterceptor.java
new file mode 100644
index 0000000..ac18432
--- /dev/null
+++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/interceptor/AuthInterceptor.java
@@ -0,0 +1,60 @@
+/*
+ * 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.dubbo.admin.interceptor;
+
+import org.apache.dubbo.admin.annotation.Authority;
+import org.apache.dubbo.admin.controller.UserController;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.lang.reflect.Method;
+
+@Component
+public class AuthInterceptor extends HandlerInterceptorAdapter {
+ @Value("${admin.check.authority:true}")
+ private boolean checkAuthority;
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ if (!(handler instanceof HandlerMethod) || !checkAuthority) {
+ return true;
+ }
+ HandlerMethod handlerMethod = (HandlerMethod) handler;
+ Method method = handlerMethod.getMethod();
+ Authority authority = method.getDeclaredAnnotation(Authority.class);
+ if (null == authority) {
+ authority = method.getDeclaringClass().getDeclaredAnnotation(Authority.class);
+ }
+ if (null != authority && authority.needLogin()) {
+ String authorization = request.getHeader("Authorization");
+ UserController.User user = UserController.tokenMap.get(authorization);
+ if (null != user && System.currentTimeMillis() - user.getLastUpdateTime() <= 1000 * 60 * 15) {
+ user.setLastUpdateTime(System.currentTimeMillis());
+ return true;
+ }
+ response.setStatus(HttpStatus.UNAUTHORIZED.value());
+ return false;
+ } else {
+ return true;
+ }
+ }
+}
diff --git a/dubbo-admin-server/src/main/resources/application-test.properties b/dubbo-admin-server/src/main/resources/application-test.properties
index 2363252..075c357 100644
--- a/dubbo-admin-server/src/main/resources/application-test.properties
+++ b/dubbo-admin-server/src/main/resources/application-test.properties
@@ -19,3 +19,4 @@
admin.registry.address=zookeeper://127.0.0.1:2182
admin.config-center=zookeeper://127.0.0.1:2182
admin.metadata.address=zookeeper://127.0.0.1:2182
+admin.check.authority=false
\ No newline at end of file
diff --git a/dubbo-admin-server/src/main/resources/application.properties b/dubbo-admin-server/src/main/resources/application.properties
index 056946d..a8a79c1 100644
--- a/dubbo-admin-server/src/main/resources/application.properties
+++ b/dubbo-admin-server/src/main/resources/application.properties
@@ -20,6 +20,8 @@ admin.registry.address=zookeeper://127.0.0.1:2181
admin.config-center=zookeeper://127.0.0.1:2181
admin.metadata-report.address=zookeeper://127.0.0.1:2181
+admin.root.user.name=root
+admin.root.user.password=root
#group
admin.registry.group=dubbo
admin.config-center.group=dubbo
diff --git a/dubbo-admin-ui/src/App.vue b/dubbo-admin-ui/src/App.vue
index e83bfd4..5bc1add 100644
--- a/dubbo-admin-ui/src/App.vue
+++ b/dubbo-admin-ui/src/App.vue
@@ -16,26 +16,12 @@
-->
<template>
- <v-app :dark="dark">
- <drawer></drawer>
- <toolbar></toolbar>
- <v-content>
- <router-view/>
- </v-content>
- <footers></footers>
- </v-app>
+ <div id="app">
+ <router-view/>
+ </div>
</template>
<script>
- import Drawer from '@/components/public/Drawer'
- import Toolbar from '@/components/public/Toolbar'
- import Footers from '@/components/public/Footers'
-
export default {
- components: {
- Drawer,
- Toolbar,
- Footers
- },
data () {
return {
dark: false
diff --git a/dubbo-admin-ui/src/App.vue b/dubbo-admin-ui/src/Index.vue
similarity index 75%
copy from dubbo-admin-ui/src/App.vue
copy to dubbo-admin-ui/src/Index.vue
index e83bfd4..d1a00ee 100644
--- a/dubbo-admin-ui/src/App.vue
+++ b/dubbo-admin-ui/src/Index.vue
@@ -14,7 +14,6 @@
- See the License for the specific language governing permissions and
- limitations under the License.
-->
-
<template>
<v-app :dark="dark">
<drawer></drawer>
@@ -25,12 +24,13 @@
<footers></footers>
</v-app>
</template>
+
<script>
import Drawer from '@/components/public/Drawer'
import Toolbar from '@/components/public/Toolbar'
import Footers from '@/components/public/Footers'
-
export default {
+ name: 'Index',
components: {
Drawer,
Toolbar,
@@ -43,7 +43,20 @@
},
created () {
window.getApp = this
- },
- name: 'App'
+ window.getApp.$on('APP_LOGOUT', () => {
+ console.log('logout')
+ window.getApp.$axios.delete('/user/logout')
+ .then(response => {
+ if (response.status === 200 && response.data) {
+ localStorage.removeItem('token')
+ localStorage.removeItem('username')
+ window.getApp.$router.replace('/login')
+ }
+ })
+ })
+ }
}
</script>
+
+<style scoped>
+</style>
diff --git a/dubbo-admin-ui/src/Login.vue b/dubbo-admin-ui/src/Login.vue
new file mode 100644
index 0000000..e4004c8
--- /dev/null
+++ b/dubbo-admin-ui/src/Login.vue
@@ -0,0 +1,100 @@
+<!--
+ - 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.
+ -->
+<template>
+ <v-app id="inspire">
+ <v-content>
+ <v-container fluid fill-height>
+ <v-layout align-center justify-center>
+ <v-flex xs12 sm8 md4>
+ <v-card class="elevation-12">
+ <v-toolbar dark color="primary">
+ <v-spacer></v-spacer>
+ </v-toolbar>
+ <v-card-text>
+ <v-form action='login' >
+ <v-text-field required
+ name="username"
+ v-model="userName"
+ append-icon="person"
+ :label="$t('userName')" type="text">
+ </v-text-field>
+ <v-text-field
+ name="input-10-2"
+ :label="$t('password')"
+ hint="At least 8 characters"
+ min="8"
+ :append-icon="e2 ? 'visibility' : 'visibility_off'"
+ :append-icon-cb="() => (e2 = !e2)"
+ v-model="password"
+ class="input-group--focused"
+ :type="e2 ? 'password' : 'text'"
+ ></v-text-field>
+
+ <v-card-actions>
+ <v-spacer></v-spacer>
+ <v-btn @click="login" color="primary">{{$t('login')}}<v-icon>send</v-icon></v-btn>
+ <v-spacer></v-spacer>
+ </v-card-actions>
+ </v-form>
+ </v-card-text>
+ </v-card>
+ </v-flex>
+ </v-layout>
+ </v-container>
+ </v-content>
+ <footers></footers>
+ </v-app>
+</template>
+
+<script>
+ import Footers from '@/components/public/Footers'
+ export default {
+ name: 'Login',
+ data: () => ({
+ userName: '',
+ password: '',
+ e2: true
+ }),
+ components: {
+ Footers
+ },
+ methods: {
+ login: function () {
+ let userName = this.userName
+ let password = this.password
+ let vm = this
+ this.$axios.get('/user/login', {
+ params: {
+ userName,
+ password
+ }
+ }).then(response => {
+ if (response.status === 200 && response.data) {
+ localStorage.setItem('token', response.data)
+ localStorage.setItem('username', userName)
+ this.$router.replace('/')
+ } else {
+ vm.$notify('Username or password error,please try again')
+ }
+ })
+ }
+ }
+ }
+</script>
+
+<style scoped>
+</style>
diff --git a/dubbo-admin-ui/src/components/http-common.js b/dubbo-admin-ui/src/components/http-common.js
index 3421e56..96890bf 100644
--- a/dubbo-admin-ui/src/components/http-common.js
+++ b/dubbo-admin-ui/src/components/http-common.js
@@ -22,13 +22,23 @@ let instance = axios.create({
baseURL: '/api/dev'
})
+instance.interceptors.request.use(config => {
+ let token = localStorage.getItem('token')
+ if (token) {
+ config.headers.Authorization = token
+ }
+ return config
+})
+
instance.interceptors.response.use((response) => {
return response
}, (error) => {
if (error.message.indexOf('Network Error') >= 0) {
Vue.prototype.$notify.error('Network error, please check your network settings!')
} else if (error.response.status === HttpStatus.UNAUTHORIZED) {
- // TODO jump to url
+ localStorage.removeItem('token')
+ localStorage.removeItem('username')
+ Vue.prototype.$notify.error('Authorized failed,please login.')
} else if (error.response.status >= HttpStatus.BAD_REQUEST) {
Vue.prototype.$notify.error(error.response.data.message)
}
diff --git a/dubbo-admin-ui/src/components/public/Toolbar.vue b/dubbo-admin-ui/src/components/public/Toolbar.vue
index 66fdd35..7c1ee22 100644
--- a/dubbo-admin-ui/src/components/public/Toolbar.vue
+++ b/dubbo-admin-ui/src/components/public/Toolbar.vue
@@ -73,7 +73,7 @@
</v-menu>
<!--login user info-->
- <v-menu offset-y origin="center center" :nudge-bottom="10" transition="scale-transition" v-if="false">
+ <v-menu offset-y origin="center center" :nudge-bottom="10" transition="scale-transition">
<v-btn icon large flat slot="activator">
<v-avatar size="30px">
<img src="@/assets/avatar.png" alt="Logined User" />
@@ -113,14 +113,6 @@
}
},
{
- icon: 'settings',
- href: '#',
- title: 'Settings',
- click: (e) => {
- console.log(e)
- }
- },
- {
icon: 'fullscreen_exit',
href: '#',
title: 'Logout',
@@ -167,6 +159,10 @@
} else {
this.selectedLang = 'English'
}
+ let username = localStorage.getItem('username')
+ if (username) {
+ this.items[0].title = this.$t('userName') + ':' + username
+ }
}
}
</script>
diff --git a/dubbo-admin-ui/src/lang/en.js b/dubbo-admin-ui/src/lang/en.js
index d8f44ef..e762f39 100644
--- a/dubbo-admin-ui/src/lang/en.js
+++ b/dubbo-admin-ui/src/lang/en.js
@@ -156,5 +156,8 @@ export default {
methods: 'Methods',
testModule: {
searchServiceHint: 'Service ID, org.apache.dubbo.demo.api.DemoService, * for fuzzy search, press Enter to search'
- }
+ },
+ userName: 'User Name',
+ password: 'Password',
+ login: 'Login'
}
diff --git a/dubbo-admin-ui/src/lang/zh.js b/dubbo-admin-ui/src/lang/zh.js
index d13f7b6..cf74e33 100644
--- a/dubbo-admin-ui/src/lang/zh.js
+++ b/dubbo-admin-ui/src/lang/zh.js
@@ -156,5 +156,8 @@ export default {
methods: '方法列表',
testModule: {
searchServiceHint: '服务ID, org.apache.dubbo.demo.api.DemoService, 使用 * 进行模糊查找, 按回车键查询'
- }
+ },
+ userName: '用户名',
+ password: '密码',
+ login: '登录'
}
diff --git a/dubbo-admin-ui/src/main.js b/dubbo-admin-ui/src/main.js
index b161680..908cb98 100644
--- a/dubbo-admin-ui/src/main.js
+++ b/dubbo-admin-ui/src/main.js
@@ -56,3 +56,18 @@ new Vue({
components: { App },
template: '<App/>'
})
+
+router.beforeEach((to, from, next) => {
+ if (to.matched.some(record => record.meta.requireLogin)) {
+ if (localStorage.getItem('token')) {
+ next()
+ } else {
+ next({
+ path: '/login',
+ query: {redirect: to.fullPath}
+ })
+ }
+ } else {
+ next()
+ }
+})
diff --git a/dubbo-admin-ui/src/router/index.js b/dubbo-admin-ui/src/router/index.js
index 4b1d318..e61ffe2 100644
--- a/dubbo-admin-ui/src/router/index.js
+++ b/dubbo-admin-ui/src/router/index.js
@@ -31,79 +31,140 @@ import ServiceMock from '@/components/test/ServiceMock'
import ServiceMetrics from '@/components/metrics/ServiceMetrics'
import ServiceRelation from '@/components/metrics/ServiceRelation'
import Management from '@/components/Management'
+import Index from '@/Index'
+import Login from '@/Login'
Vue.use(Router)
export default new Router({
routes: [
{
- path: '/service',
- name: 'ServiceSearch',
- component: ServiceSearch
- },
- {
- path: '/serviceDetail',
- name: 'ServiceDetail',
- component: ServiceDetail
- },
- {
- path: '/testMethod',
- name: 'TestMethod',
- component: TestMethod
- },
- {
- path: '/governance/routingRule',
- name: 'RoutingRule',
- component: RoutingRule
- },
- {
- path: '/governance/tagRule',
- name: 'TagRule',
- component: TagRule
- },
- {
- path: '/governance/access',
- name: 'AccessControl',
- component: AccessControl
- },
- {
- path: '/governance/loadbalance',
- name: 'LoadBalance',
- component: LoadBalance
- },
- { path: '/governance/weight',
- name: 'WeightAdjust',
- component: WeightAdjust
- },
- {
- path: '/governance/config',
- name: 'Overrides',
- component: Overrides
- },
- {
- path: '/test',
- name: 'ServiceTest',
- component: ServiceTest
- },
- {
- path: '/mock',
- name: 'ServiceMock',
- component: ServiceMock
- },
- {
- path: '/metrics/index',
- name: 'ServiceMetrics',
- component: ServiceMetrics
- },
- {
- path: '/metrics/relation',
- name: 'ServiceRelation',
- component: ServiceRelation
- },
- {
- path: '/management',
- name: 'Management',
- component: Management
+ path: '/',
+ name: 'Index',
+ component: Index,
+ meta: {
+ requireLogin: true
+ },
+ children: [
+ {
+ path: '/service',
+ name: 'ServiceSearch',
+ component: ServiceSearch,
+ meta: {
+ requireLogin: true
+ }
+ },
+ {
+ path: '/serviceDetail',
+ name: 'ServiceDetail',
+ component: ServiceDetail,
+ meta: {
+ requireLogin: true
+ }
+ },
+ {
+ path: '/testMethod',
+ name: 'TestMethod',
+ component: TestMethod,
+ meta: {
+ requireLogin: true
+ }
+ },
+ {
+ path: '/governance/routingRule',
+ name: 'RoutingRule',
+ component: RoutingRule,
+ meta: {
+ requireLogin: true
+ }
+ },
+ {
+ path: '/governance/tagRule',
+ name: 'TagRule',
+ component: TagRule,
+ meta: {
+ requireLogin: true
+ }
+ },
+ {
+ path: '/governance/access',
+ name: 'AccessControl',
+ component: AccessControl,
+ meta: {
+ requireLogin: true
+ }
+ },
+ {
+ path: '/governance/loadbalance',
+ name: 'LoadBalance',
+ component: LoadBalance,
+ meta: {
+ requireLogin: true
+ }
+ },
+ {
+ path: '/governance/weight',
+ name: 'WeightAdjust',
+ component: WeightAdjust,
+ meta: {
+ requireLogin: true
+ }
+ },
+ {
+ path: '/governance/config',
+ name: 'Overrides',
+ component: Overrides,
+ meta: {
+ requireLogin: true
+ }
+ },
+ {
+ path: '/test',
+ name: 'ServiceTest',
+ component: ServiceTest,
+ meta: {
+ requireLogin: true
+ }
+ },
+ {
+ path: '/mock',
+ name: 'ServiceMock',
+ component: ServiceMock,
+ meta: {
+ requireLogin: true
+ }
+ },
+ {
+ path: '/metrics/index',
+ name: 'ServiceMetrics',
+ component: ServiceMetrics,
+ meta: {
+ requireLogin: true
+ }
+ },
+ {
+ path: '/metrics/relation',
+ name: 'ServiceRelation',
+ component: ServiceRelation,
+ meta: {
+ requireLogin: true
+ }
+ },
+ {
+ path: '/management',
+ name: 'Management',
+ component: Management,
+ meta: {
+ requireLogin: true
+ }
+ }]
+ }, {
+ path: '/login',
+ name: 'Login',
+ component: Login,
+ meta: {
+ requireLogin: false
+ }
}
]