zhaowenyu
2026-02-10 263821773852f2bea1c881462bf15e6a2a325f7c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
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);
        }
    }
}