8000 feat: 添加 DataPermissionInterceptor · cadecode/uni-boot-cloud@8b88816 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8b88816

Browse files
committed
feat: 添加 DataPermissionInterceptor
1 parent d331e03 commit 8b88816

File tree

5 files changed

+216
-0
lines changed

5 files changed

+216
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.github.cadecode.uniboot.common.plugin.mybatis.annotation;
2+
3+
import java.lang.annotation.*;
4+
5+
/**
6+
* 数据权限注解
7+
*
8+
* @author Cade Li
9+
* @since 2024/5/23
10+
*/
11+
@Target({ElementType.TYPE, ElementType.METHOD})
12+
@Retention(RetentionPolicy.RUNTIME)
13+
@Documented
14+
public @interface UseDataScope {
15+
16+
String DEFAULT_FIELD = "data_scope";
17+
String DEFAULT_RESOLVER_NAME = "defaultDataScopeResolver";
18+
19+
/**
20+
* 是否启用过滤
21+
*/
22+
boolean enableFilter() default true;
23+
24+
/**
25+
* 需要作用的字段名
26+
*/
27+
String field() default "";
28+
29+
/**
30+
* 权限范围解析器 Bean 名称
31+
*/
32+
String resolverName() default "";
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package com.github.cadecode.uniboot.common.plugin.mybatis.aspect;
2+
3+
import cn.hutool.core.util.ObjUtil;
4+
import com.github.cadecode.uniboot.common.core.util.SpringUtil;
5+
import com.github.cadecode.uniboot.common.plugin.mybatis.annotation.UseDataScope;
6+
import com.github.cadecode.uniboot.common.plugin.mybatis.handler.DataScopeResolver;
7+
import lombok.*;
8+
import lombok.extern.slf4j.Slf4j;
9+
import org.aspectj.lang.JoinPoint;
10+
import org.aspectj.lang.annotation.After;
11+
import org.aspectj.lang.annotation.Aspect;
12+
import org.aspectj.lang.annotation.Before;
13+
import org.aspectj.lang.annotation.Pointcut;
14+
import org.aspectj.lang.reflect.MethodSignature;
15+
import org.springframework.stereotype.Component;
16+
17+
import java.util.Objects;
18+
19+
/**
20+
* 数据权限注解切面
21+
*
22+
* @author Cade Li
23+
* @since 2024/5/23
24+
*/
25+
@Slf4j
26+
@RequiredArgsConstructor
27+
@Aspect
28+
@Component
29+
public class DataScopeAspect {
30+
31+
private static final ThreadLocal<DataScopeParam> DATA_SCOPE_LOCAL = new ThreadLocal<>();
32+
33+
public static DataScopeParam currDataScope() {
34+
return DATA_SCOPE_LOCAL.get();
35+
}
36+
37+
@Pointcut("@within(com.github.cadecode.uniboot.common.plugin.mybatis.annotation.UseDataScope) " +
38+
"|| @annotation(com.github.cadecode.uniboot.common.plugin.mybatis.annotation.UseDataScope)")
39+
public void pointCut() {
40+
41+
}
42+
43+
@Before("pointCut()")
44+
public void before(JoinPoint point) {
45+
DataScopeParam dataScopeParam = getDataScopeParam(point);
46+
DATA_SCOPE_LOCAL.set(dataScopeParam);
47+
}
48+
49+
@After("pointCut()")
50+
public void after(JoinPoint point) {
51+
DATA_SCOPE_LOCAL.remove();
52+
}
53+
54+
/**
55+
* 获取数据权限注解内容
56+
*/
57+
private DataScopeParam getDataScopeParam(JoinPoint point) {
58+
MethodSignature methodSignature = (MethodSignature) point.getSignature();
59+
// 获取方法上的注解内容
60+
UseDataScope useDataScopeM = methodSignature.getMethod().getAnnotation(UseDataScope.class);
61+
// 获取类上的注解内容
62+
UseDataScope useDataScopeC = methodSignature.getMethod().getDeclaringClass().getAnnotation(UseDataScope.class);
63+
DataScopeParam dataScopeParam = new DataScopeParam();
64+
if (Objects.isNull(useDataScopeM) && Objects.isNull(useDataScopeC)) {
65+
return dataScopeParam;
66+
}
67+
// 方法上有注解
68+
if (Objects.nonNull(useDataScopeM)) {
69+
dataScopeParam.setEnableFilter(useDataScopeM.enableFilter());
70+
// 方法上有注解,且类上也有
71+
if (Objects.nonNull(useDataScopeC)) {
72+
dataScopeParam.setField(ObjUtil.defaultIfEmpty(useDataScopeM.field(),
73+
ObjUtil.defaultIfEmpty(useDataScopeC.field(), UseDataScope.DEFAULT_FIELD)));
74+
dataScopeParam.setResolverName(ObjUtil.defaultIfEmpty(useDataScopeM.resolverName(),
75+
ObjUtil.defaultIfEmpty(useDataScopeC.field(), UseDataScope.DEFAULT_RESOLVER_NAME)));
76+
} else {
77+
// 方法上有注解,类上无注解
78+
dataScopeParam.setField(ObjUtil.defaultIfEmpty(useDataScopeM.field(), UseDataScope.DEFAULT_FIELD));
79+
dataScopeParam.setResolverName(ObjUtil.defaultIfEmpty(useDataScopeM.resolverName(), UseDataScope.DEFAULT_RESOLVER_NAME));
80+
}
81+
} else {
82+
// 方法上无注解,类上有注解
83+
dataScopeParam.setEnableFilter(useDataScopeC.enableFilter());
84+
dataScopeParam.setField(ObjUtil.defaultIfEmpty(useDataScopeC.field(), UseDataScope.DEFAULT_FIELD));
85+
dataScopeParam.setResolverName(ObjUtil.defaultIfEmpty(useDataScopeC.resolverName(), UseDataScope.DEFAULT_RESOLVER_NAME));
86+
}
87+
// 从容器取出数据范围解析器
88+
DataScopeResolver scopeResolver = SpringUtil.getBean(dataScopeParam.getResolverName(), DataScopeResolver.class);
89+
dataScopeParam.setDataScopeResolver(scopeResolver);
90+
return dataScopeParam;
91+
}
92+
93+
@Data
94+
@AllArgsConstructor
95+
@NoArgsConstructor
96+
@Builder
97+
public static class DataScopeParam {
98+
99+
private boolean enableFilter;
100+
private String field;
101+
private String resolverName;
102+
private DataScopeResolver dataScopeResolver;
103+
104+
}
105+
106+
}

common/plugin/mybatis/src/main/java/com/github/cadecode/uniboot/common/plugin/mybatis/config/MybatisConfig.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.github.cadecode.uniboot.common.plugin.mybatis.config;
22

33
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
4+
import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
5+
import com.github.cadecode.uniboot.common.plugin.mybatis.handler.DataScopePermissionHandler;
46
import org.springframework.context.annotation.Bean;
57
import org.springframework.context.annotation.Configuration;
68

@@ -19,6 +21,10 @@ public class MybatisConfig {
1921
@Bean
2022
public MybatisPlusInterceptor mybatisPlusInterceptor() {
2123
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
24+
// 数据权限插件
25+
DataPermissionInterceptor dataPermissionInterceptor = new DataPermissionInterceptor(new DataScopePermissionHandler());
26+
interceptor.addInnerInterceptor(dataPermissionInterceptor);
27+
2228
// 添加分页插件,动态获取数据库类型
2329
// interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
2430
return interceptor;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.github.cadecode.uniboot.common.plugin.mybatis.handler;
2+
3+
import cn.hutool.core.util.ObjUtil;
4+
import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
5+
import com.github.cadecode.uniboot.common.plugin.mybatis.aspect.DataScopeAspect;
6+
import com.github.cadecode.uniboot.common.plugin.mybatis.aspect.DataScopeAspect.DataScopeParam;
7+
import lombok.extern.slf4j.Slf4j;
8+
import net.sf.jsqlparser.expression.Expression;
9+
import net.sf.jsqlparser.expression.StringValue;
10+
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
11+
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
12+
import net.sf.jsqlparser.expression.operators.relational.InExpression;
13+
import net.sf.jsqlparser.schema.Column;
14+
15+
import java.util.List;
16+
import java.util.Objects;
17+
import java.util.stream.Collectors;
18+
19+
/**
20+
* mybatis-plus 数据权限处理器
21+
*
22+
* @author Cade Li
23+
* @since 2024/5/23
24+
*/
25+
@Slf4j
26+
public class DataScopePermissionHandler implements DataPermissionHandler {
27+
28+
@Override
29+
public Expression getSqlSegment(Expression where, String mappedStatementId) {
30+
DataScopeParam dataScopeParam = DataScopeAspect.currDataScope();
31+
if (Objects.isNull(dataScopeParam) || !dataScopeParam.isEnableFilter()) {
32+
return where;
33+
}
34+
DataScopeResolver dataScopeResolver = dataScopeParam.getDataScopeResolver();
35+
// admin 不作限制
36+
if (dataScopeResolver.isAdmin()) {
37+
return where;
38+
}
39+
InExpression inExpression = new InExpression();
40+
inExpression.setLeftExpression(new Column(dataScopeParam.getField()));
41+
List<Object> scopes = dataScopeResolver.getScopes();
42+
// 没配置数据权限时不作限制
43+
if (ObjUtil.isEmpty(scopes)) {
44+
return where;
45+
}
46+
ExpressionList expressionList = new ExpressionList(scopes.stream().map(o -> new StringValue(o.toString())).collect(Collectors.toList()));
47+
inExpression.setRightItemsList(expressionList);
48+
if (Objects.isNull(where)) {
49+
return inExpression;
50+
}
51+
return new AndExpression(where, inExpression);
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.github.cadecode.uniboot.common.plugin.mybatis.handler;
2+
3+
import java.util.List;
4+
5+
/**
6+
* 数据权限范围
7+
*
8+
* @author Cade Li
9+
* @since 2024/5/23
10+
*/
11+
public interface DataScopeResolver {
12+
13+
List<Object> getScopes();
14+
15+
default boolean isAdmin() {
16+
return false;
17+
}
18+
}

0 commit comments

Comments
 (0)
0