一、添加依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
二、添加注解,用户判断是否是要数据权限
package com.tuling.dynamic.datasource.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataScope {
/**
* 是否启用
*/
boolean enabled() default true;
/**
* 表别名
*/
String tableAlias() default "";
/**
* 表字段
*/
String tableField() default "user_id";
}
三、配置一个mybatis拦截器对象
package com.tuling.dynamic.datasource.anno;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisConfigInterceptor {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
return new MybatisPlusInterceptor();
}
}
四、添加一个拦截器,并根据用户查询权限修改sql
package com.tuling.dynamic.datasource.anno;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.MultiDataPermissionHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import lombok.RequiredArgsConstructor;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.parser.Node;
import net.sf.jsqlparser.parser.SimpleNode;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.PlainSelect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
@Component
public class PermissionRunner implements ApplicationRunner {
@Resource
private MybatisPlusInterceptor mybatisPlusInterceptor;
@Resource
private PermissionHandling permissionHandling;
@Override
public void run(ApplicationArguments args) throws Exception {
mybatisPlusInterceptor.addInnerInterceptor(new DataPermissionInterceptor(new InnerDataPermissionHandler(permissionHandling)));
}
@RequiredArgsConstructor
public static class InnerDataPermissionHandler implements MultiDataPermissionHandler {
private final PermissionHandling permissionHandling;
@Override
public Expression getSqlSegment(Table table, Expression where, String mappedStatementId) {
try {
Class<?> mapperClazz = Class.forName(mappedStatementId.substring(0, mappedStatementId.lastIndexOf(".")));
String methodName = mappedStatementId.substring(mappedStatementId.lastIndexOf(".") + 1);
// 获取自身类中的所有方法,不包括继承。与访问权限无关
Method[] methods = mapperClazz.getDeclaredMethods();
if (methods.length == 0) {
return null;
}
Method targetMethods = Arrays.stream(methods).filter(method -> method.getName().equals(methodName)).findFirst().orElse(null);
if (targetMethods == null) {
return null;
}
DataScope dataScopeAnnotationMethod = targetMethods.getAnnotation(DataScope.class);
if (ObjectUtils.isEmpty(dataScopeAnnotationMethod) || !dataScopeAnnotationMethod.enabled()) {
return null;
} else {
// 跳过join中的on条件表达式拼装
if (where != null && where.getASTNode() != null && where.getASTNode().jjtGetParent().jjtGetParent().toString().equals("JoinerExpression")) {
return null;
}
return buildDataScopeByAnnotation(dataScopeAnnotationMethod);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 根据注解构建express语句
*/
private Expression buildDataScopeByAnnotation(DataScope dataScopeAnnotationMethod) {
//可以判断是否是管理员,如果是管理员就是全部权限
// 构建权限语句
// 构造用户in表达式。
Long currLoginUserId = 1L; //获取当前登录用户id
InExpression userIdsInExpression = new InExpression();
//获取当前用户能够管理的用户权限
List<Long> userIds = permissionHandling.getUserIdsByUserId(currLoginUserId);
// 权限适用范围为全部
if (userIds == null) {
return null;
}
if (userIds.isEmpty()) {
throw new RuntimeException("当前权限适用范围内暂无用户数据筛选");
}
ExpressionList expressionList = new ExpressionList();
userIds.forEach(a -> expressionList.addExpressions(new StringValue(a.toString())));
// 设置左边的字段表达式,右边设置值。
userIdsInExpression.setLeftExpression(buildColumn(dataScopeAnnotationMethod.tableAlias(), dataScopeAnnotationMethod.tableField()));
userIdsInExpression.setRightItemsList(expressionList);
return userIdsInExpression;
}
/**
* 构建Column
*
* @param tableAlias 表别名
* @param columnName 字段名称
* @return 带表别名字段
*/
private Column buildColumn(String tableAlias, String columnName) {
if (StringUtils.isNotEmpty(tableAlias)) {
columnName = tableAlias + "." + columnName;
}
return new Column(columnName);
}
}
}
五、权限查询接口
package com.tuling.dynamic.datasource.anno; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; @Component public class PermissionHandling { /** * 根据用户Id获取权限范围的用户Id * * @param userId 用户Id * @return {@link List}<{@link String}> */ List<Long> getUserIdsByUserId(Long userId){ return List.of(1L,2L,3L); } }
浙公网安备 33010602011771号