package com.ard.framework.aspectj; import java.util.ArrayList; import java.util.List; import java.util.Objects; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; import com.ard.common.annotation.DataScopePlus; import com.ard.common.constant.UserConstants; import com.ard.common.core.domain.entity.SysRole; import com.ard.common.core.domain.entity.SysUser; import com.ard.common.core.domain.model.LoginUser; import com.ard.common.core.text.Convert; import com.ard.common.utils.SecurityUtils; import com.ard.common.utils.StringUtils; import com.ard.framework.security.context.PermissionContextHolder; import com.baomidou.mybatisplus.core.conditions.AbstractWrapper; /** * MyBatis-Plus 专用数据权限切面 * 仅处理带有 @MyBatisPlusDataScope 注解的方法,且参数包含 QueryWrapper/LambdaQueryWrapper */ @Aspect @Component public class DataScopeAspectPlus { /** * 全部数据权限 */ public static final String DATA_SCOPE_ALL = "1"; /** * 自定数据权限(部门维度) */ public static final String DATA_SCOPE_CUSTOM = "2"; /** * 部门数据权限(仅本部门) */ public static final String DATA_SCOPE_DEPT = "3"; /** * 部门及以下数据权限 */ public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; /** * 仅本人数据权限 */ public static final String DATA_SCOPE_SELF = "5"; /** * 拦截带有 @MyBatisPlusDataScope 注解的方法,处理部门权限 */ @Before("@annotation(dataScope)") public void doBefore(JoinPoint point, DataScopePlus dataScope) throws Throwable { // 遍历方法参数,找到 Wrapper 类型的参数 AbstractWrapper wrapper = findWrapperFromArgs(point.getArgs()); if (wrapper != null) { handleDataScope(wrapper, dataScope); // 找到后执行权限逻辑 } } /** * 从方法参数中找到 AbstractWrapper 类型的参数(兼容任意位置) */ private AbstractWrapper findWrapperFromArgs(Object[] args) { if (args == null || args.length == 0) { return null; } for (Object arg : args) { // 判断是否为 MyBatis-Plus 的 Wrapper 类型 if (arg instanceof AbstractWrapper) { return (AbstractWrapper) arg; } } return null; // 没找到 Wrapper,不执行权限过滤 } /** * 处理部门数据权限 */ protected void handleDataScope(AbstractWrapper wrapper, DataScopePlus dataScope) { LoginUser loginUser = SecurityUtils.getLoginUser(); if (StringUtils.isNotNull(loginUser)) { SysUser currentUser = loginUser.getUser(); // 超级管理员跳过权限过滤 if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) { String permission = StringUtils.defaultIfEmpty( dataScope.permission(), PermissionContextHolder.getContext() ); // 生成部门权限条件并注入 Wrapper generateDeptScopeSql(wrapper, currentUser, dataScope.deptAlias(), dataScope.userAlias(), permission); } } } /** * 仅生成部门维度的权限 SQL(移除用户相关逻辑) */ private void generateDeptScopeSql(AbstractWrapper wrapper, SysUser user, String deptAlias, String userAlias, String permission) { StringBuilder sqlBuilder = new StringBuilder(); List conditions = new ArrayList<>(); List customRoleIds = new ArrayList<>(); // 收集拥有自定义部门权限的角色ID user.getRoles().forEach(role -> { if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) { customRoleIds.add(Convert.toStr(role.getRoleId())); } }); // 遍历角色生,生成对应的数据权限条件 for (SysRole role : user.getRoles()) { String dataScope = role.getDataScope(); // 跳过已处理的权限类型或禁用角色 if (conditions.contains(dataScope) || StringUtils.equals(role.getStatus(), UserConstants.ROLE_DISABLE)) { continue; } // 跳过不包含目标权限的角色 if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) { continue; } // 仅保留部门相关的权限逻辑(移除用户权限) if (DATA_SCOPE_ALL.equals(dataScope)) { // 全部权限:清空条件 sqlBuilder.setLength(0); conditions.add(dataScope); break; } else if (DATA_SCOPE_CUSTOM.equals(dataScope)) { // 自定义部门权限:关联角色-部门表 if (customRoleIds.size() > 1) { sqlBuilder.append(StringUtils.format( " OR {}.dept_id IN (SELECT dept_id FROM sys_role_dept WHERE role_id IN ({}) )", deptAlias, String.join(",", customRoleIds) )); } else { sqlBuilder.append(StringUtils.format( " OR {}.dept_id IN (SELECT dept_id FROM sys_role_dept WHERE role_id = {} )", deptAlias, role.getRoleId() )); } } else if (DATA_SCOPE_DEPT.equals(dataScope)) { // 本部门权限:仅当前用户所属部门 sqlBuilder.append(StringUtils.format( " OR {}.dept_id = {}", deptAlias, user.getDeptId() )); } else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) { // 本部门及下属部门权限:通过部门表 ancestors 字段递归查询 sqlBuilder.append(StringUtils.format( " OR {}.dept_id IN (SELECT dept_id FROM sys_dept WHERE dept_id = {} OR find_in_set({}, ancestors) )", deptAlias, user.getDeptId(), user.getDeptId() )); } else if (DATA_SCOPE_SELF.equals(dataScope)) { // 仅本人权限:关联用户表 if (StringUtils.isNotBlank(userAlias)) { sqlBuilder.append(StringUtils.format( " OR {}.user_id = {}", userAlias, user.getUserId() )); } else { // 无用户别名时强制过滤(不查询任何数据) sqlBuilder.append(StringUtils.format( " OR {}.dept_id = 0", deptAlias )); } } conditions.add(dataScope); } // 无匹配角色时,强制过滤(不查询任何数据) if (conditions.isEmpty()) { sqlBuilder.append(StringUtils.format(" OR {}.dept_id = 0", deptAlias)); } // 注入部门权限条件 if (sqlBuilder.length() > 0) { String dataScopeSql = sqlBuilder.substring(4); // 去除开头的 "OR " wrapper.apply(dataScopeSql); } } }