From c85bb1f62dc712dfc885cb9291e58e52defe8bf9 Mon Sep 17 00:00:00 2001 From: JEECG <445654970@qq.com> Date: Thu, 16 Oct 2025 11:05:33 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90sa-token=E3=80=91=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E6=9D=83=E9=99=90=E6=B3=A8=E8=A7=A3=E5=92=8C=E6=9D=83=E9=99=90?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/controller/SysDictController.java | 31 ++---- .../controller/SysPermissionController.java | 97 ++++++++++++------- 2 files changed, 73 insertions(+), 55 deletions(-) diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDictController.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDictController.java index 9de865676..5b2c5093d 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDictController.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDictController.java @@ -9,9 +9,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; -import org.apache.shiro.SecurityUtils; -import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.apache.shiro.subject.Subject; +import org.jeecg.common.util.LoginUserUtils; +import cn.dev33.satoken.annotation.SaCheckPermission; import org.jeecg.common.api.vo.Result; import org.jeecg.common.config.TenantContext; import org.jeecg.common.constant.CacheConstant; @@ -23,7 +22,6 @@ import org.jeecg.common.system.vo.DictQuery; import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.util.*; import org.jeecg.config.mybatis.MybatisPlusSaasConfig; -import org.jeecg.config.shiro.ShiroRealm; import org.jeecg.modules.system.entity.SysDict; import org.jeecg.modules.system.entity.SysDictItem; import org.jeecg.modules.system.model.SysDictTree; @@ -73,8 +71,6 @@ public class SysDictController { public RedisTemplate redisTemplate; @Autowired private RedisUtil redisUtil; - @Autowired - private ShiroRealm shiroRealm; @RequestMapping(value = "/list", method = RequestMethod.GET) public Result> queryPageList( @@ -389,7 +385,7 @@ public class SysDictController { * @param sysDict * @return */ - @RequiresPermissions("system:dict:add") + @SaCheckPermission("system:dict:add") @RequestMapping(value = "/add", method = RequestMethod.POST) public Result add(@RequestBody SysDict sysDict) { Result result = new Result(); @@ -410,7 +406,7 @@ public class SysDictController { * @param sysDict * @return */ - @RequiresPermissions("system:dict:edit") + @SaCheckPermission("system:dict:edit") @RequestMapping(value = "/edit", method = { RequestMethod.PUT,RequestMethod.POST }) public Result edit(@RequestBody SysDict sysDict) { Result result = new Result(); @@ -432,7 +428,7 @@ public class SysDictController { * @param id * @return */ - @RequiresPermissions("system:dict:delete") + @SaCheckPermission("system:dict:delete") @RequestMapping(value = "/delete", method = RequestMethod.DELETE) @CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true) public Result delete(@RequestParam(name="id",required=true) String id) { @@ -451,7 +447,7 @@ public class SysDictController { * @param ids * @return */ - @RequiresPermissions("system:dict:deleteBatch") + @SaCheckPermission("system:dict:deleteBatch") @RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE) @CacheEvict(value= {CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true) public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { @@ -490,7 +486,7 @@ public class SysDictController { // redisTemplate.delete(keys6); // redisTemplate.delete(keys7); - //update-begin-author:liusq date:20230404 for: [issue/4358]springCache中的清除缓存的操作使用了“keys” + // springCache中的清除缓存的操作使用了“keys” redisUtil.removeAll(CacheConstant.SYS_DICT_CACHE); redisUtil.removeAll(CacheConstant.SYS_ENABLE_DICT_CACHE); redisUtil.removeAll(CacheConstant.SYS_DICT_TABLE_CACHE); @@ -499,15 +495,6 @@ public class SysDictController { redisUtil.removeAll(CacheConstant.SYS_DEPART_IDS_CACHE); redisUtil.removeAll("jmreport:cache:dict"); redisUtil.removeAll("jmreport:cache:dictTable"); - //update-end-author:liusq date:20230404 for: [issue/4358]springCache中的清除缓存的操作使用了“keys” - - //update-begin---author:scott ---date:2024-06-18 for:【TV360X-1320】分配权限必须退出重新登录才生效,造成很多用户困扰--- - // 清除当前用户的授权缓存信息 - Subject currentUser = SecurityUtils.getSubject(); - if (currentUser.isAuthenticated()) { - shiroRealm.clearCache(currentUser.getPrincipals()); - } - //update-end---author:scott ---date::2024-06-18 for:【TV360X-1320】分配权限必须退出重新登录才生效,造成很多用户困扰--- return result; } @@ -564,7 +551,7 @@ public class SysDictController { * @param * @return */ - @RequiresPermissions("system:dict:importExcel") + @SaCheckPermission("system:dict:importExcel") @RequestMapping(value = "/importExcel", method = RequestMethod.POST) public Result importExcel(HttpServletRequest request, HttpServletResponse response) { MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; @@ -703,7 +690,7 @@ public class SysDictController { * @param ids 被删除的字典ID,多个id用半角逗号分割 * @return */ - @RequiresPermissions("system:dict:deleteRecycleBin") + @SaCheckPermission("system:dict:deleteRecycleBin") @RequestMapping(value = "/deleteRecycleBin", method = RequestMethod.DELETE) public Result deleteRecycleBin(@RequestParam("ids") String ids) { try { diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysPermissionController.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysPermissionController.java index 9b8100a70..dbb920585 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysPermissionController.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysPermissionController.java @@ -1,14 +1,15 @@ package org.jeecg.modules.system.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.extern.slf4j.Slf4j; -import org.apache.shiro.SecurityUtils; -import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.apache.shiro.subject.Subject; import org.jeecg.common.api.vo.Result; +import org.jeecg.common.util.LoginUserUtils; import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.constant.SymbolConstant; import org.jeecg.common.exception.JeecgBootException; @@ -16,7 +17,6 @@ import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.util.Md5Util; import org.jeecg.common.util.oConvertUtils; import org.jeecg.config.JeecgBaseConfig; -import org.jeecg.config.shiro.ShiroRealm; import org.jeecg.modules.base.service.BaseCommonService; import org.jeecg.modules.system.constant.DefIndexConst; import org.jeecg.modules.system.entity.*; @@ -67,9 +67,6 @@ public class SysPermissionController { @Autowired private ISysRoleIndexService sysRoleIndexService; - - @Autowired - private ShiroRealm shiroRealm; /** * 子菜单 @@ -81,7 +78,7 @@ public class SysPermissionController { * * @return */ - //@RequiresPermissions("system:permission:list") + //@SaCheckPermission("system:permission:list") @RequestMapping(value = "/list", method = RequestMethod.GET) public Result> list(SysPermission sysPermission, HttpServletRequest req) { long start = System.currentTimeMillis(); @@ -244,8 +241,8 @@ public class SysPermissionController { public Result getUserPermissionByToken(HttpServletRequest request) { Result result = new Result(); try { - //直接获取当前用户不适用前端token - LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + //直接获取当前用户 + LoginUser loginUser = LoginUserUtils.getSessionUser(); if (oConvertUtils.isEmpty(loginUser)) { return Result.error("请登录系统!"); } @@ -357,7 +354,7 @@ public class SysPermissionController { public Result getPermCode() { try { // 直接获取当前用户 - LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + LoginUser loginUser = LoginUserUtils.getSessionUser(); if (oConvertUtils.isEmpty(loginUser)) { return Result.error("请登录系统!"); } @@ -398,7 +395,7 @@ public class SysPermissionController { * @param permission * @return */ - @RequiresPermissions("system:permission:add") + @SaCheckPermission("system:permission:add") @RequestMapping(value = "/add", method = RequestMethod.POST) public Result add(@RequestBody SysPermission permission) { Result result = new Result(); @@ -418,7 +415,7 @@ public class SysPermissionController { * @param permission * @return */ - @RequiresPermissions("system:permission:edit") + @SaCheckPermission("system:permission:edit") @RequestMapping(value = "/edit", method = { RequestMethod.PUT, RequestMethod.POST }) public Result edit(@RequestBody SysPermission permission) { Result result = new Result<>(); @@ -460,7 +457,7 @@ public class SysPermissionController { * @param id * @return */ - @RequiresPermissions("system:permission:delete") + @SaCheckPermission("system:permission:delete") @RequestMapping(value = "/delete", method = RequestMethod.DELETE) public Result delete(@RequestParam(name = "id", required = true) String id) { Result result = new Result<>(); @@ -479,7 +476,7 @@ public class SysPermissionController { * @param ids * @return */ - @RequiresPermissions("system:permission:deleteBatch") + @SaCheckPermission("system:permission:deleteBatch") @RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE) public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) { Result result = new Result<>(); @@ -587,7 +584,7 @@ public class SysPermissionController { * @return */ @RequestMapping(value = "/saveRolePermission", method = RequestMethod.POST) - @RequiresPermissions("system:permission:saveRole") + @SaCheckPermission("system:permission:saveRole") public Result saveRolePermission(@RequestBody JSONObject json) { long start = System.currentTimeMillis(); Result result = new Result<>(); @@ -596,27 +593,61 @@ public class SysPermissionController { String permissionIds = json.getString("permissionIds"); String lastPermissionIds = json.getString("lastpermissionIds"); this.sysRolePermissionService.saveRolePermission(roleId, permissionIds, lastPermissionIds); - //update-begin---author:wangshuai ---date:20220316 for:[VUEN-234]用户管理角色授权添加敏感日志------------ - LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); - baseCommonService.addLog("修改角色ID: "+roleId+" 的权限配置,操作人: " +loginUser.getUsername() ,CommonConstant.LOG_TYPE_2, 2); - //update-end---author:wangshuai ---date:20220316 for:[VUEN-234]用户管理角色授权添加敏感日志------------ + + // 清除拥有该角色的所有用户的权限和角色缓存 + clearRolePermissionCache(roleId); + + LoginUser loginUser = LoginUserUtils.getSessionUser(); + baseCommonService.addLog("修改角色ID: " +roleId+" 的权限配置,操作人: " +loginUser.getUsername() ,CommonConstant.LOG_TYPE_2, 2); result.success("保存成功!"); log.info("======角色授权成功=====耗时:" + (System.currentTimeMillis() - start) + "毫秒"); - - //update-begin---author:scott ---date:2024-06-18 for:【TV360X-1320】分配权限必须退出重新登录才生效,造成很多用户困扰--- - // 清除当前用户的授权缓存信息 - Subject currentUser = SecurityUtils.getSubject(); - if (currentUser.isAuthenticated()) { - shiroRealm.clearCache(currentUser.getPrincipals()); - } - //update-end---author:scott ---date::2024-06-18 for:【TV360X-1320】分配权限必须退出重新登录才生效,造成很多用户困扰--- - } catch (Exception e) { result.error500("授权失败!"); log.error(e.getMessage(), e); } return result; } + + /** + * 清除拥有指定角色的所有用户的权限和角色缓存 + *

原理:查询拥有该角色的所有用户,调用 StpInterfaceImpl.clearUserCache() 清除缓存

+ * + * @param roleId 角色ID + */ + private void clearRolePermissionCache(String roleId) { + log.info("开始清除角色权限缓存 [ roleId={} ]", roleId); + List usernameList = new ArrayList<>(); + + // 分页查询拥有该角色的用户(避免一次性加载大量数据) + int pageNo = 1, pageSize = 100; + while (true) { + Page page = new Page<>(pageNo, pageSize); + IPage userPage = sysUserService.getUserByRoleId(page, roleId, null, null); + + if (userPage.getRecords().isEmpty()) { + break; + } + + // 收集用户名 + for (SysUser user : userPage.getRecords()) { + usernameList.add(user.getUsername()); + } + + // 判断是否还有下一页 + if (pageNo >= userPage.getPages()) { + break; + } + pageNo++; + } + + // 批量清除缓存 + if (!usernameList.isEmpty()) { + org.jeecg.config.satoken.StpInterfaceImpl.clearUserCache(usernameList); + log.info("角色权限缓存清理完成 [ roleId={}, affectedUsers={} ]", roleId, usernameList.size()); + } else { + log.info("该角色下无用户,无需清除缓存 [ roleId={} ]", roleId); + } + } private void getTreeList(List treeList, List metaList, SysPermissionTree temp) { for (SysPermission permission : metaList) { @@ -924,7 +955,7 @@ public class SysPermissionController { * @param sysPermissionDataRule * @return */ - @RequiresPermissions("system:permission:addRule") + @SaCheckPermission("system:permission:addRule") @RequestMapping(value = "/addPermissionRule", method = RequestMethod.POST) public Result addPermissionRule(@RequestBody SysPermissionDataRule sysPermissionDataRule) { Result result = new Result(); @@ -939,7 +970,7 @@ public class SysPermissionController { return result; } - @RequiresPermissions("system:permission:editRule") + @SaCheckPermission("system:permission:editRule") @RequestMapping(value = "/editPermissionRule", method = { RequestMethod.PUT, RequestMethod.POST }) public Result editPermissionRule(@RequestBody SysPermissionDataRule sysPermissionDataRule) { Result result = new Result(); @@ -959,7 +990,7 @@ public class SysPermissionController { * @param id * @return */ - @RequiresPermissions("system:permission:deleteRule") + @SaCheckPermission("system:permission:deleteRule") @RequestMapping(value = "/deletePermissionRule", method = RequestMethod.DELETE) public Result deletePermissionRule(@RequestParam(name = "id", required = true) String id) { Result result = new Result(); @@ -1016,7 +1047,7 @@ public class SysPermissionController { * @return */ @RequestMapping(value = "/saveDepartPermission", method = RequestMethod.POST) - @RequiresPermissions("system:permission:saveDepart") + @SaCheckPermission("system:permission:saveDepart") public Result saveDepartPermission(@RequestBody JSONObject json) { long start = System.currentTimeMillis(); Result result = new Result<>();