From b08be2aa6501835c6fdd8c27998daa7ed7e9c1bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=99=93=E4=B8=9C?= <763795151@qq.com> Date: Tue, 16 May 2023 21:23:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9D=83=E9=99=90=E9=85=8D=E7=BD=AE=E3=80=81?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E7=94=A8=E6=88=B7=E3=80=81=E8=A7=92=E8=89=B2?= =?UTF-8?q?=E9=85=8D=E7=BD=AE.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xuxd/kafka/console/beans/LoginResult.java | 4 ++ .../controller/UserManageController.java | 9 ++- .../console/dao/SysPermissionMapper.java | 2 + .../xuxd/kafka/console/dao/SysRoleMapper.java | 2 + .../kafka/console/interceptor/AuthFilter.java | 1 + .../console/service/impl/AuthServiceImpl.java | 55 ++++++++++++++++++- .../service/impl/UserManageServiceImpl.java | 4 +- src/main/resources/db/data-h2.sql | 51 ++++++++++------- ui/src/App.vue | 4 +- ui/src/directives/action.js | 5 +- ui/src/store/index.js | 12 +++- ui/src/store/mutation-types.js | 1 + ui/src/utils/constants.js | 1 + ui/src/utils/local-cache.js | 8 +++ ui/src/views/Home.vue | 2 +- ui/src/views/cluster/Cluster.vue | 1 + ui/src/views/login/Login.vue | 2 + 17 files changed, 137 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/xuxd/kafka/console/beans/LoginResult.java b/src/main/java/com/xuxd/kafka/console/beans/LoginResult.java index 75faeaa..030fe17 100644 --- a/src/main/java/com/xuxd/kafka/console/beans/LoginResult.java +++ b/src/main/java/com/xuxd/kafka/console/beans/LoginResult.java @@ -2,6 +2,8 @@ package com.xuxd.kafka.console.beans; import lombok.Data; +import java.util.List; + /** * @author: xuxd * @date: 2023/5/14 20:44 @@ -10,4 +12,6 @@ import lombok.Data; public class LoginResult { private String token; + + private List permissions; } diff --git a/src/main/java/com/xuxd/kafka/console/controller/UserManageController.java b/src/main/java/com/xuxd/kafka/console/controller/UserManageController.java index bf5d62c..7c81ead 100644 --- a/src/main/java/com/xuxd/kafka/console/controller/UserManageController.java +++ b/src/main/java/com/xuxd/kafka/console/controller/UserManageController.java @@ -1,12 +1,15 @@ package com.xuxd.kafka.console.controller; import com.xuxd.kafka.console.aspect.annotation.ControllerLog; +import com.xuxd.kafka.console.beans.Credentials; import com.xuxd.kafka.console.beans.dto.SysPermissionDTO; import com.xuxd.kafka.console.beans.dto.SysRoleDTO; import com.xuxd.kafka.console.beans.dto.SysUserDTO; import com.xuxd.kafka.console.service.UserManageService; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; + /** * @author: xuxd * @date: 2023/4/11 21:34 @@ -74,7 +77,11 @@ public class UserManageController { @ControllerLog("更新密码") @PostMapping("/user/password") - public Object updatePassword(@RequestBody SysUserDTO userDTO) { + public Object updatePassword(@RequestBody SysUserDTO userDTO, HttpServletRequest request) { + Credentials credentials = (Credentials)request.getAttribute("credentials"); + if (credentials != null && !credentials.isInvalid()) { + userDTO.setUsername(credentials.getUsername()); + } return userManageService.updatePassword(userDTO); } } diff --git a/src/main/java/com/xuxd/kafka/console/dao/SysPermissionMapper.java b/src/main/java/com/xuxd/kafka/console/dao/SysPermissionMapper.java index f88ff78..23fd893 100644 --- a/src/main/java/com/xuxd/kafka/console/dao/SysPermissionMapper.java +++ b/src/main/java/com/xuxd/kafka/console/dao/SysPermissionMapper.java @@ -2,6 +2,7 @@ package com.xuxd.kafka.console.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xuxd.kafka.console.beans.dos.SysPermissionDO; +import org.apache.ibatis.annotations.Mapper; /** * 系统权限 . @@ -9,5 +10,6 @@ import com.xuxd.kafka.console.beans.dos.SysPermissionDO; * @author: xuxd * @date: 2023/4/11 21:21 **/ +@Mapper public interface SysPermissionMapper extends BaseMapper { } diff --git a/src/main/java/com/xuxd/kafka/console/dao/SysRoleMapper.java b/src/main/java/com/xuxd/kafka/console/dao/SysRoleMapper.java index d70ad4b..f54d998 100644 --- a/src/main/java/com/xuxd/kafka/console/dao/SysRoleMapper.java +++ b/src/main/java/com/xuxd/kafka/console/dao/SysRoleMapper.java @@ -2,10 +2,12 @@ package com.xuxd.kafka.console.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xuxd.kafka.console.beans.dos.SysRoleDO; +import org.apache.ibatis.annotations.Mapper; /** * @author: xuxd * @date: 2023/4/11 21:22 **/ +@Mapper public interface SysRoleMapper extends BaseMapper { } diff --git a/src/main/java/com/xuxd/kafka/console/interceptor/AuthFilter.java b/src/main/java/com/xuxd/kafka/console/interceptor/AuthFilter.java index 0a32555..aea95f1 100644 --- a/src/main/java/com/xuxd/kafka/console/interceptor/AuthFilter.java +++ b/src/main/java/com/xuxd/kafka/console/interceptor/AuthFilter.java @@ -58,6 +58,7 @@ public class AuthFilter implements Filter { response.setStatus(HttpStatus.UNAUTHORIZED.value()); return; } + request.setAttribute("credentials", credentials); filterChain.doFilter(servletRequest, servletResponse); } diff --git a/src/main/java/com/xuxd/kafka/console/service/impl/AuthServiceImpl.java b/src/main/java/com/xuxd/kafka/console/service/impl/AuthServiceImpl.java index d44d4af..783d1bf 100644 --- a/src/main/java/com/xuxd/kafka/console/service/impl/AuthServiceImpl.java +++ b/src/main/java/com/xuxd/kafka/console/service/impl/AuthServiceImpl.java @@ -4,30 +4,51 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.xuxd.kafka.console.beans.Credentials; import com.xuxd.kafka.console.beans.LoginResult; import com.xuxd.kafka.console.beans.ResponseData; +import com.xuxd.kafka.console.beans.dos.SysPermissionDO; +import com.xuxd.kafka.console.beans.dos.SysRoleDO; import com.xuxd.kafka.console.beans.dos.SysUserDO; import com.xuxd.kafka.console.beans.dto.LoginUserDTO; import com.xuxd.kafka.console.config.AuthConfig; +import com.xuxd.kafka.console.dao.SysPermissionMapper; +import com.xuxd.kafka.console.dao.SysRoleMapper; import com.xuxd.kafka.console.dao.SysUserMapper; import com.xuxd.kafka.console.service.AuthService; import com.xuxd.kafka.console.utils.AuthUtil; import com.xuxd.kafka.console.utils.UUIDStrUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.stereotype.Service; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + /** * @author: xuxd * @date: 2023/5/14 19:01 **/ @Slf4j @Service -public class AuthServiceImpl implements AuthService { +public class AuthServiceImpl implements AuthService, SmartInitializingSingleton { private final SysUserMapper userMapper; + private final SysRoleMapper roleMapper; + + private final SysPermissionMapper permissionMapper; + private final AuthConfig authConfig; - public AuthServiceImpl(SysUserMapper userMapper, AuthConfig authConfig) { + private final Map permCache = new HashMap<>(); + + public AuthServiceImpl(SysUserMapper userMapper, + SysRoleMapper roleMapper, + SysPermissionMapper permissionMapper, + AuthConfig authConfig) { this.userMapper = userMapper; + this.roleMapper = roleMapper; + this.permissionMapper = permissionMapper; this.authConfig = authConfig; } @@ -48,7 +69,37 @@ public class AuthServiceImpl implements AuthService { credentials.setExpiration(System.currentTimeMillis() + authConfig.getExpireHours() * 3600 * 1000); String token = AuthUtil.generateToken(authConfig.getSecret(), credentials); LoginResult loginResult = new LoginResult(); + List permissions = new ArrayList<>(); + String roleIds = userDO.getRoleIds(); + if (StringUtils.isNotEmpty(roleIds)) { + List roleIdList = Arrays.stream(roleIds.split(",")).map(String::trim).filter(StringUtils::isNotEmpty).collect(Collectors.toList()); + roleIdList.forEach(roleId -> { + Long rId = Long.valueOf(roleId); + SysRoleDO roleDO = roleMapper.selectById(rId); + String permissionIds = roleDO.getPermissionIds(); + if (StringUtils.isNotEmpty(permissionIds)) { + List permIds = Arrays.stream(permissionIds.split(",")).map(String::trim). + filter(StringUtils::isNotEmpty).map(Long::valueOf).collect(Collectors.toList()); + permIds.forEach(id -> { + String permission = permCache.get(id).getPermission(); + if (StringUtils.isNotEmpty(permission)) { + permissions.add(permission); + } else { + log.error("角色:{},权限id: {},不存在", roleId, id); + } + }); + } + }); + } loginResult.setToken(token); + loginResult.setPermissions(permissions); return ResponseData.create().data(loginResult).success(); } + + @Override + public void afterSingletonsInstantiated() { + List roleDOS = permissionMapper.selectList(null); + Map map = roleDOS.stream().collect(Collectors.toMap(SysPermissionDO::getId, Function.identity(), (e1, e2) -> e1)); + permCache.putAll(map); + } } diff --git a/src/main/java/com/xuxd/kafka/console/service/impl/UserManageServiceImpl.java b/src/main/java/com/xuxd/kafka/console/service/impl/UserManageServiceImpl.java index c0255f2..beb65e3 100644 --- a/src/main/java/com/xuxd/kafka/console/service/impl/UserManageServiceImpl.java +++ b/src/main/java/com/xuxd/kafka/console/service/impl/UserManageServiceImpl.java @@ -213,7 +213,9 @@ public class UserManageServiceImpl implements UserManageService { SysUserDO userDO = userDTO.toDO(); userDO.setSalt(UUIDStrUtil.random()); userDO.setPassword(UUIDStrUtil.generate(userDTO.getPassword(), userDO.getSalt())); - userMapper.updateById(userDO); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("username", userDTO.getUsername()); + userMapper.update(userDO, wrapper); return ResponseData.create().success(); } } diff --git a/src/main/resources/db/data-h2.sql b/src/main/resources/db/data-h2.sql index 775b1be..ac396b6 100644 --- a/src/main/resources/db/data-h2.sql +++ b/src/main/resources/db/data-h2.sql @@ -6,13 +6,11 @@ insert into t_sys_permission(id, name,type,parent_id,permission) values(0,'主页',0,null,'home'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(10,'集群',0,null,'cluster'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(11,'集群信息',1,10,'cluster'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(11,'集群',0,null,'cluster'); insert into t_sys_permission(id, name,type,parent_id,permission) values(12,'属性配置',1,11,'cluster:property-config'); insert into t_sys_permission(id, name,type,parent_id,permission) values(13,'日志配置',1,11,'cluster:log-config'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(20,'Topic',0,null,'topic'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(21,'topic',1,20,'topic'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(21,'Topic',0,null,'topic'); insert into t_sys_permission(id, name,type,parent_id,permission) values(22,'刷新',1,21,'topic:load'); insert into t_sys_permission(id, name,type,parent_id,permission) values(23,'新增',1,21,'topic:add'); insert into t_sys_permission(id, name,type,parent_id,permission) values(24,'批量删除',1,21,'topic:batch-del'); @@ -26,8 +24,7 @@ insert into t_sys_permission(id, name,type,parent_id,permission) values(31,'变 insert into t_sys_permission(id, name,type,parent_id,permission) values(32,'发送统计',1,21,'topic:send-count'); insert into t_sys_permission(id, name,type,parent_id,permission) values(33,'限流',1,21,'topic:replication-sync-throttle'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(40,'消费组',0,null,'group'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(41,'消费组',1,40,'group:load'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(41,'消费组',0,null,'group'); insert into t_sys_permission(id, name,type,parent_id,permission) values(42,'新增订阅',1,41,'group:add'); insert into t_sys_permission(id, name,type,parent_id,permission) values(43,'删除',1,41,'group:del'); insert into t_sys_permission(id, name,type,parent_id,permission) values(44,'消费端',1,41,'group:client'); @@ -39,8 +36,7 @@ insert into t_sys_permission(id, name,type,parent_id,permission) values(49,'重 insert into t_sys_permission(id, name,type,parent_id,permission) values(50,'位移分区',1,41,'group:offset-partition'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(60,'消息',0,null,'message'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(61,'消息',1,60,'message'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(61,'消息',0,null,'message'); insert into t_sys_permission(id, name,type,parent_id,permission) values(62,'根据时间查询',1,61,'message:search-time'); insert into t_sys_permission(id, name,type,parent_id,permission) values(63,'根据偏移查询',1,61,'message:search-offset'); insert into t_sys_permission(id, name,type,parent_id,permission) values(64,'在线发送',1,61,'message:send'); @@ -59,14 +55,31 @@ insert into t_sys_permission(id, name,type,parent_id,permission) values(100,'Acl insert into t_sys_permission(id, name,type,parent_id,permission) values(101,'资源授权',1,100,'acl:authority'); insert into t_sys_permission(id, name,type,parent_id,permission) values(102,'新增权限',1,101,'acl:authority:add'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(120,'用户',0,null,'user-manage'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(121,'用户列表',1,120,'user-manage:user'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(122,'新增',1,121,'user-manage:user:add'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(123,'删除',1,121,'user-manage:user:del'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(124,'重置密码',1,121,'user-manage:user:reset-pass'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(125,'分配角色',1,121,'user-manage:user:change-role'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(126,'角色列表',1,120,'user-manage:role'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(127,'保存',1,126,'user-manage:role:save'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(128,'删除',1,126,'user-manage:role:del'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(129,'权限列表',1,120,'user-manage:permission'); -insert into t_sys_permission(id, name,type,parent_id,permission) values(130,'个人设置',1,120,'user-manage:setting'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(140,'用户',0,null,'user-manage'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(141,'用户列表',1,140,'user-manage:user'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(142,'新增',1,141,'user-manage:user:add'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(143,'删除',1,141,'user-manage:user:del'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(144,'重置密码',1,141,'user-manage:user:reset-pass'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(145,'分配角色',1,141,'user-manage:user:change-role'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(146,'角色列表',1,140,'user-manage:role'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(147,'保存',1,146,'user-manage:role:save'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(148,'删除',1,146,'user-manage:role:del'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(149,'权限列表',1,140,'user-manage:permission'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(150,'个人设置',1,140,'user-manage:setting'); + +insert into t_sys_permission(id, name,type,parent_id,permission) values(160,'运维',0,null,'op'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(161,'集群切换',1,160,'op:cluster-switch'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(162,'新增集群',1,161,'op:cluster-switch:add'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(163,'切换',1,161,'op:cluster-switch:switch'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(164,'编辑',1,161,'op:cluster-switch:edit'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(165,'删除',1,161,'op:cluster-switch:del'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(166,'配置限流',1,160,'op:config-throttle'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(167,'解除限流',1,160,'op:remove-throttle'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(168,'首选副本作leader',1,160,'op:replication-preferred'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(169,'副本变更详情',1,160,'op:replication-update-detail'); +insert into t_sys_permission(id, name,type,parent_id,permission) values(170,'副本重分配',1,160,'op:replication-reassign'); + + +insert into t_sys_role(id, role_name, description, permission_ids) VALUES ( 1,'超级管理员','超级管理员','12,13,22,23,24,25,26,27,28,29,30,31,32,33,42,43,44,45,46,47,48,49,50,62,63,64,65,81,82,83,84,85,86,101,102,141,142,143,144,145,146,147,148,149,150,161,162,163,164,165,166,167,168,169,170' ); + +insert into t_sys_user(id, username, password, salt, role_ids) VALUES ( 1,'admin','3a3e4d32-5247-321b-9efb-9cbf60b2bf6c','e6973cfc-7583-4baa-8802-65ded1268ab6','1' ); \ No newline at end of file diff --git a/ui/src/App.vue b/ui/src/App.vue index 1516803..78fcc5b 100644 --- a/ui/src/App.vue +++ b/ui/src/App.vue @@ -44,7 +44,7 @@ import { KafkaClusterApi, AuthApi } from "@/utils/api"; import request from "@/utils/request"; import { mapMutations, mapState } from "vuex"; -import {deleteToken, deleteUsername, getClusterInfo, getUsername} from "@/utils/local-cache"; +import {deleteToken, deleteUsername, getClusterInfo, getPermissions, getUsername} from "@/utils/local-cache"; import notification from "ant-design-vue/lib/notification"; import { AUTH, CLUSTER } from "@/store/mutation-types"; @@ -71,9 +71,11 @@ export default { switchCluster: CLUSTER.SWITCH, enableAuth: AUTH.ENABLE, setUsername: AUTH.SET_USERNAME, + setPermissions: AUTH.SET_PERMISSIONS, }), beforeLoadFn() { this.setUsername(getUsername()); + this.setPermissions(getPermissions()); }, intAuthState() { request({ diff --git a/ui/src/directives/action.js b/ui/src/directives/action.js index 1131a46..291ee78 100644 --- a/ui/src/directives/action.js +++ b/ui/src/directives/action.js @@ -1,9 +1,12 @@ import Vue from "vue"; +import Store from "@/store"; const action = Vue.directive("action", { inserted: function (el, binding) { const actionName = binding.arg; - if (actionName != "action") { + const enableAuth = Store.state.auth.enable; + const permissions = Store.state.auth.permissions; + if (enableAuth && (!permissions || permissions.indexOf(actionName) < 0)) { (el.parentNode && el.parentNode.removeChild(el)) || (el.style.display = "none"); } diff --git a/ui/src/store/index.js b/ui/src/store/index.js index 99595d0..1441759 100644 --- a/ui/src/store/index.js +++ b/ui/src/store/index.js @@ -1,7 +1,12 @@ import Vue from "vue"; import Vuex from "vuex"; import { CLUSTER, AUTH } from "@/store/mutation-types"; -import { setClusterInfo, setToken, setUsername } from "@/utils/local-cache"; +import { + setClusterInfo, + setPermissions, + setToken, + setUsername, +} from "@/utils/local-cache"; Vue.use(Vuex); @@ -15,6 +20,7 @@ export default new Vuex.Store({ auth: { enable: false, username: "", + permissions: [], }, }, mutations: { @@ -42,6 +48,10 @@ export default new Vuex.Store({ setUsername(username); state.auth.username = username; }, + [AUTH.SET_PERMISSIONS](state, permissions) { + setPermissions(permissions); + state.auth.permissions = permissions; + }, }, actions: {}, modules: {}, diff --git a/ui/src/store/mutation-types.js b/ui/src/store/mutation-types.js index 090b5b9..f219f18 100644 --- a/ui/src/store/mutation-types.js +++ b/ui/src/store/mutation-types.js @@ -6,4 +6,5 @@ export const AUTH = { ENABLE: "enable", SET_TOKEN: "setToken", SET_USERNAME: "setUsername", + SET_PERMISSIONS: "setPermissions", }; diff --git a/ui/src/utils/constants.js b/ui/src/utils/constants.js index c5432b9..0fcb8dd 100644 --- a/ui/src/utils/constants.js +++ b/ui/src/utils/constants.js @@ -8,4 +8,5 @@ export const Cache = { token: "access_token", username: "login_user", enableAuth: "enable_auth", + permissions: "permissions", }; diff --git a/ui/src/utils/local-cache.js b/ui/src/utils/local-cache.js index be8a174..80ae0f1 100644 --- a/ui/src/utils/local-cache.js +++ b/ui/src/utils/local-cache.js @@ -37,6 +37,14 @@ export function getUsername() { return localStorage.getItem(Cache.username); } +export function setPermissions(permissions) { + localStorage.setItem(Cache.permissions, permissions); +} + +export function getPermissions() { + return localStorage.getItem(Cache.permissions); +} + // export function setEnableAuth(enable) { // localStorage.setItem() // } diff --git a/ui/src/views/Home.vue b/ui/src/views/Home.vue index 10b43dd..55eac8e 100644 --- a/ui/src/views/Home.vue +++ b/ui/src/views/Home.vue @@ -1,6 +1,6 @@