【sa-token】替换权限注解和权限缓存处理

This commit is contained in:
JEECG
2025-10-16 11:05:33 +08:00
parent b4fa11a605
commit c85bb1f62d
2 changed files with 73 additions and 55 deletions

View File

@ -9,9 +9,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils; import org.jeecg.common.util.LoginUserUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions; import cn.dev33.satoken.annotation.SaCheckPermission;
import org.apache.shiro.subject.Subject;
import org.jeecg.common.api.vo.Result; import org.jeecg.common.api.vo.Result;
import org.jeecg.common.config.TenantContext; import org.jeecg.common.config.TenantContext;
import org.jeecg.common.constant.CacheConstant; 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.system.vo.LoginUser;
import org.jeecg.common.util.*; import org.jeecg.common.util.*;
import org.jeecg.config.mybatis.MybatisPlusSaasConfig; 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.SysDict;
import org.jeecg.modules.system.entity.SysDictItem; import org.jeecg.modules.system.entity.SysDictItem;
import org.jeecg.modules.system.model.SysDictTree; import org.jeecg.modules.system.model.SysDictTree;
@ -73,8 +71,6 @@ public class SysDictController {
public RedisTemplate<String, Object> redisTemplate; public RedisTemplate<String, Object> redisTemplate;
@Autowired @Autowired
private RedisUtil redisUtil; private RedisUtil redisUtil;
@Autowired
private ShiroRealm shiroRealm;
@RequestMapping(value = "/list", method = RequestMethod.GET) @RequestMapping(value = "/list", method = RequestMethod.GET)
public Result<IPage<SysDict>> queryPageList( public Result<IPage<SysDict>> queryPageList(
@ -389,7 +385,7 @@ public class SysDictController {
* @param sysDict * @param sysDict
* @return * @return
*/ */
@RequiresPermissions("system:dict:add") @SaCheckPermission("system:dict:add")
@RequestMapping(value = "/add", method = RequestMethod.POST) @RequestMapping(value = "/add", method = RequestMethod.POST)
public Result<SysDict> add(@RequestBody SysDict sysDict) { public Result<SysDict> add(@RequestBody SysDict sysDict) {
Result<SysDict> result = new Result<SysDict>(); Result<SysDict> result = new Result<SysDict>();
@ -410,7 +406,7 @@ public class SysDictController {
* @param sysDict * @param sysDict
* @return * @return
*/ */
@RequiresPermissions("system:dict:edit") @SaCheckPermission("system:dict:edit")
@RequestMapping(value = "/edit", method = { RequestMethod.PUT,RequestMethod.POST }) @RequestMapping(value = "/edit", method = { RequestMethod.PUT,RequestMethod.POST })
public Result<SysDict> edit(@RequestBody SysDict sysDict) { public Result<SysDict> edit(@RequestBody SysDict sysDict) {
Result<SysDict> result = new Result<SysDict>(); Result<SysDict> result = new Result<SysDict>();
@ -432,7 +428,7 @@ public class SysDictController {
* @param id * @param id
* @return * @return
*/ */
@RequiresPermissions("system:dict:delete") @SaCheckPermission("system:dict:delete")
@RequestMapping(value = "/delete", method = RequestMethod.DELETE) @RequestMapping(value = "/delete", method = RequestMethod.DELETE)
@CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true) @CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
public Result<SysDict> delete(@RequestParam(name="id",required=true) String id) { public Result<SysDict> delete(@RequestParam(name="id",required=true) String id) {
@ -451,7 +447,7 @@ public class SysDictController {
* @param ids * @param ids
* @return * @return
*/ */
@RequiresPermissions("system:dict:deleteBatch") @SaCheckPermission("system:dict:deleteBatch")
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE) @RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
@CacheEvict(value= {CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true) @CacheEvict(value= {CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
public Result<SysDict> deleteBatch(@RequestParam(name="ids",required=true) String ids) { public Result<SysDict> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
@ -490,7 +486,7 @@ public class SysDictController {
// redisTemplate.delete(keys6); // redisTemplate.delete(keys6);
// redisTemplate.delete(keys7); // 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_DICT_CACHE);
redisUtil.removeAll(CacheConstant.SYS_ENABLE_DICT_CACHE); redisUtil.removeAll(CacheConstant.SYS_ENABLE_DICT_CACHE);
redisUtil.removeAll(CacheConstant.SYS_DICT_TABLE_CACHE); redisUtil.removeAll(CacheConstant.SYS_DICT_TABLE_CACHE);
@ -499,15 +495,6 @@ public class SysDictController {
redisUtil.removeAll(CacheConstant.SYS_DEPART_IDS_CACHE); redisUtil.removeAll(CacheConstant.SYS_DEPART_IDS_CACHE);
redisUtil.removeAll("jmreport:cache:dict"); redisUtil.removeAll("jmreport:cache:dict");
redisUtil.removeAll("jmreport:cache:dictTable"); 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; return result;
} }
@ -564,7 +551,7 @@ public class SysDictController {
* @param * @param
* @return * @return
*/ */
@RequiresPermissions("system:dict:importExcel") @SaCheckPermission("system:dict:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST) @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) { public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
@ -703,7 +690,7 @@ public class SysDictController {
* @param ids 被删除的字典ID多个id用半角逗号分割 * @param ids 被删除的字典ID多个id用半角逗号分割
* @return * @return
*/ */
@RequiresPermissions("system:dict:deleteRecycleBin") @SaCheckPermission("system:dict:deleteRecycleBin")
@RequestMapping(value = "/deleteRecycleBin", method = RequestMethod.DELETE) @RequestMapping(value = "/deleteRecycleBin", method = RequestMethod.DELETE)
public Result deleteRecycleBin(@RequestParam("ids") String ids) { public Result deleteRecycleBin(@RequestParam("ids") String ids) {
try { try {

View File

@ -1,14 +1,15 @@
package org.jeecg.modules.system.controller; package org.jeecg.modules.system.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 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 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.api.vo.Result;
import org.jeecg.common.util.LoginUserUtils;
import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant; import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.exception.JeecgBootException; 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.Md5Util;
import org.jeecg.common.util.oConvertUtils; import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.JeecgBaseConfig; import org.jeecg.config.JeecgBaseConfig;
import org.jeecg.config.shiro.ShiroRealm;
import org.jeecg.modules.base.service.BaseCommonService; import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.system.constant.DefIndexConst; import org.jeecg.modules.system.constant.DefIndexConst;
import org.jeecg.modules.system.entity.*; import org.jeecg.modules.system.entity.*;
@ -68,9 +68,6 @@ public class SysPermissionController {
@Autowired @Autowired
private ISysRoleIndexService sysRoleIndexService; private ISysRoleIndexService sysRoleIndexService;
@Autowired
private ShiroRealm shiroRealm;
/** /**
* 子菜单 * 子菜单
*/ */
@ -81,7 +78,7 @@ public class SysPermissionController {
* *
* @return * @return
*/ */
//@RequiresPermissions("system:permission:list") //@SaCheckPermission("system:permission:list")
@RequestMapping(value = "/list", method = RequestMethod.GET) @RequestMapping(value = "/list", method = RequestMethod.GET)
public Result<List<SysPermissionTree>> list(SysPermission sysPermission, HttpServletRequest req) { public Result<List<SysPermissionTree>> list(SysPermission sysPermission, HttpServletRequest req) {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
@ -244,8 +241,8 @@ public class SysPermissionController {
public Result<?> getUserPermissionByToken(HttpServletRequest request) { public Result<?> getUserPermissionByToken(HttpServletRequest request) {
Result<JSONObject> result = new Result<JSONObject>(); Result<JSONObject> result = new Result<JSONObject>();
try { try {
//直接获取当前用户不适用前端token //直接获取当前用户
LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); LoginUser loginUser = LoginUserUtils.getSessionUser();
if (oConvertUtils.isEmpty(loginUser)) { if (oConvertUtils.isEmpty(loginUser)) {
return Result.error("请登录系统!"); return Result.error("请登录系统!");
} }
@ -357,7 +354,7 @@ public class SysPermissionController {
public Result<?> getPermCode() { public Result<?> getPermCode() {
try { try {
// 直接获取当前用户 // 直接获取当前用户
LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); LoginUser loginUser = LoginUserUtils.getSessionUser();
if (oConvertUtils.isEmpty(loginUser)) { if (oConvertUtils.isEmpty(loginUser)) {
return Result.error("请登录系统!"); return Result.error("请登录系统!");
} }
@ -398,7 +395,7 @@ public class SysPermissionController {
* @param permission * @param permission
* @return * @return
*/ */
@RequiresPermissions("system:permission:add") @SaCheckPermission("system:permission:add")
@RequestMapping(value = "/add", method = RequestMethod.POST) @RequestMapping(value = "/add", method = RequestMethod.POST)
public Result<SysPermission> add(@RequestBody SysPermission permission) { public Result<SysPermission> add(@RequestBody SysPermission permission) {
Result<SysPermission> result = new Result<SysPermission>(); Result<SysPermission> result = new Result<SysPermission>();
@ -418,7 +415,7 @@ public class SysPermissionController {
* @param permission * @param permission
* @return * @return
*/ */
@RequiresPermissions("system:permission:edit") @SaCheckPermission("system:permission:edit")
@RequestMapping(value = "/edit", method = { RequestMethod.PUT, RequestMethod.POST }) @RequestMapping(value = "/edit", method = { RequestMethod.PUT, RequestMethod.POST })
public Result<SysPermission> edit(@RequestBody SysPermission permission) { public Result<SysPermission> edit(@RequestBody SysPermission permission) {
Result<SysPermission> result = new Result<>(); Result<SysPermission> result = new Result<>();
@ -460,7 +457,7 @@ public class SysPermissionController {
* @param id * @param id
* @return * @return
*/ */
@RequiresPermissions("system:permission:delete") @SaCheckPermission("system:permission:delete")
@RequestMapping(value = "/delete", method = RequestMethod.DELETE) @RequestMapping(value = "/delete", method = RequestMethod.DELETE)
public Result<SysPermission> delete(@RequestParam(name = "id", required = true) String id) { public Result<SysPermission> delete(@RequestParam(name = "id", required = true) String id) {
Result<SysPermission> result = new Result<>(); Result<SysPermission> result = new Result<>();
@ -479,7 +476,7 @@ public class SysPermissionController {
* @param ids * @param ids
* @return * @return
*/ */
@RequiresPermissions("system:permission:deleteBatch") @SaCheckPermission("system:permission:deleteBatch")
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE) @RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
public Result<SysPermission> deleteBatch(@RequestParam(name = "ids", required = true) String ids) { public Result<SysPermission> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
Result<SysPermission> result = new Result<>(); Result<SysPermission> result = new Result<>();
@ -587,7 +584,7 @@ public class SysPermissionController {
* @return * @return
*/ */
@RequestMapping(value = "/saveRolePermission", method = RequestMethod.POST) @RequestMapping(value = "/saveRolePermission", method = RequestMethod.POST)
@RequiresPermissions("system:permission:saveRole") @SaCheckPermission("system:permission:saveRole")
public Result<String> saveRolePermission(@RequestBody JSONObject json) { public Result<String> saveRolePermission(@RequestBody JSONObject json) {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
Result<String> result = new Result<>(); Result<String> result = new Result<>();
@ -596,21 +593,14 @@ public class SysPermissionController {
String permissionIds = json.getString("permissionIds"); String permissionIds = json.getString("permissionIds");
String lastPermissionIds = json.getString("lastpermissionIds"); String lastPermissionIds = json.getString("lastpermissionIds");
this.sysRolePermissionService.saveRolePermission(roleId, permissionIds, 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); clearRolePermissionCache(roleId);
//update-end---author:wangshuai ---date:20220316 for[VUEN-234]用户管理角色授权添加敏感日志------------
LoginUser loginUser = LoginUserUtils.getSessionUser();
baseCommonService.addLog("修改角色ID: " +roleId+" 的权限配置,操作人: " +loginUser.getUsername() ,CommonConstant.LOG_TYPE_2, 2);
result.success("保存成功!"); result.success("保存成功!");
log.info("======角色授权成功=====耗时:" + (System.currentTimeMillis() - start) + "毫秒"); 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) { } catch (Exception e) {
result.error500("授权失败!"); result.error500("授权失败!");
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
@ -618,6 +608,47 @@ public class SysPermissionController {
return result; return result;
} }
/**
* 清除拥有指定角色的所有用户的权限和角色缓存
* <p>原理:查询拥有该角色的所有用户,调用 StpInterfaceImpl.clearUserCache() 清除缓存</p>
*
* @param roleId 角色ID
*/
private void clearRolePermissionCache(String roleId) {
log.info("开始清除角色权限缓存 [ roleId={} ]", roleId);
List<String> usernameList = new ArrayList<>();
// 分页查询拥有该角色的用户(避免一次性加载大量数据)
int pageNo = 1, pageSize = 100;
while (true) {
Page<SysUser> page = new Page<>(pageNo, pageSize);
IPage<SysUser> 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<SysPermissionTree> treeList, List<SysPermission> metaList, SysPermissionTree temp) { private void getTreeList(List<SysPermissionTree> treeList, List<SysPermission> metaList, SysPermissionTree temp) {
for (SysPermission permission : metaList) { for (SysPermission permission : metaList) {
String tempPid = permission.getParentId(); String tempPid = permission.getParentId();
@ -924,7 +955,7 @@ public class SysPermissionController {
* @param sysPermissionDataRule * @param sysPermissionDataRule
* @return * @return
*/ */
@RequiresPermissions("system:permission:addRule") @SaCheckPermission("system:permission:addRule")
@RequestMapping(value = "/addPermissionRule", method = RequestMethod.POST) @RequestMapping(value = "/addPermissionRule", method = RequestMethod.POST)
public Result<SysPermissionDataRule> addPermissionRule(@RequestBody SysPermissionDataRule sysPermissionDataRule) { public Result<SysPermissionDataRule> addPermissionRule(@RequestBody SysPermissionDataRule sysPermissionDataRule) {
Result<SysPermissionDataRule> result = new Result<SysPermissionDataRule>(); Result<SysPermissionDataRule> result = new Result<SysPermissionDataRule>();
@ -939,7 +970,7 @@ public class SysPermissionController {
return result; return result;
} }
@RequiresPermissions("system:permission:editRule") @SaCheckPermission("system:permission:editRule")
@RequestMapping(value = "/editPermissionRule", method = { RequestMethod.PUT, RequestMethod.POST }) @RequestMapping(value = "/editPermissionRule", method = { RequestMethod.PUT, RequestMethod.POST })
public Result<SysPermissionDataRule> editPermissionRule(@RequestBody SysPermissionDataRule sysPermissionDataRule) { public Result<SysPermissionDataRule> editPermissionRule(@RequestBody SysPermissionDataRule sysPermissionDataRule) {
Result<SysPermissionDataRule> result = new Result<SysPermissionDataRule>(); Result<SysPermissionDataRule> result = new Result<SysPermissionDataRule>();
@ -959,7 +990,7 @@ public class SysPermissionController {
* @param id * @param id
* @return * @return
*/ */
@RequiresPermissions("system:permission:deleteRule") @SaCheckPermission("system:permission:deleteRule")
@RequestMapping(value = "/deletePermissionRule", method = RequestMethod.DELETE) @RequestMapping(value = "/deletePermissionRule", method = RequestMethod.DELETE)
public Result<SysPermissionDataRule> deletePermissionRule(@RequestParam(name = "id", required = true) String id) { public Result<SysPermissionDataRule> deletePermissionRule(@RequestParam(name = "id", required = true) String id) {
Result<SysPermissionDataRule> result = new Result<SysPermissionDataRule>(); Result<SysPermissionDataRule> result = new Result<SysPermissionDataRule>();
@ -1016,7 +1047,7 @@ public class SysPermissionController {
* @return * @return
*/ */
@RequestMapping(value = "/saveDepartPermission", method = RequestMethod.POST) @RequestMapping(value = "/saveDepartPermission", method = RequestMethod.POST)
@RequiresPermissions("system:permission:saveDepart") @SaCheckPermission("system:permission:saveDepart")
public Result<String> saveDepartPermission(@RequestBody JSONObject json) { public Result<String> saveDepartPermission(@RequestBody JSONObject json) {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
Result<String> result = new Result<>(); Result<String> result = new Result<>();