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<String> conditions = new ArrayList<>();
|
List<String> 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);
|
}
|
}
|
}
|