基于Mybatis-Plus的数据权限框架
前言
近期开发使用的框架基本上都是springboot + Mybatis-plus 方便,快速。而且差不多都是单表查询,很少使用关联表。
经常会遇到需要做数据权限过滤的查询,每次都要写SQL,然后使用in的方式。非常麻烦。所以研究了一下Mybatis-plus的进阶使用。可以通过自定义SQL解析器,自定义SQL内容。
使用该方式 + 切面 的方式,实现自动添加数据权限的过滤方式。
注:我自己的工程的权限框架为shiro,可以通过修改,配置适配自己框架
设计
因为数据权限是与请求地址相关,所以将菜单与数据权限关联,角色不直接关联数据权限,角色通过菜单间接关联数据权限。如果一个用户有多个角色,并且这些角色都有分配同一个菜单的不同数据权限,则以最大权限为主。
这里就不做过多介绍。主要还是说明MP
的设计结构。
总体工程结构如下:其中DataScopeAspect
为自定义切面,将数据权限设置到参数的父类属性中。
正文
pom依赖
3.4以前的版本配置不一样,请自行查看。
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-core</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.16</version>
</dependency>
</dependencies>
1.数据权限基类
所有需要做数据权限过滤的接口入参,都需要继承该类,用于存储机构编号列表或者用户编号
package com.hongtool.mybatis.perms.domain;
import java.io.Serializable;
import java.util.List;
/**
* <p> 数据权限 传参 </p>
*
* @author hongtool
* @date 2022/11/1
*/
public class DataScopePerms implements Serializable {
private static final long serialVersionUID = 1L;
/** 创建者 */
private String userPerm;
/** 机构部门 */
private List<Long> deptPerms;
public DataScopePerms() {
}
// TODO 省略 GET 和 SET 方法
}
2.权限字段注解
注: 如果有更多的权限类型,则可以再自定义添加
1)机构部门权限
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <p> 部门权限(只能有一个,如果有多个,只会获取第一个) </p>
*
* @author hongtool
* @date 2022/11/24
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface DeptPerm {
// 字段名,如果为空,则从MyBatis-plus的解析表字段获取
String value() default "";
}
2)用户权限
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <p> 用户权限(只能有一个,同机构部门权限) </p>
*
* @author hongtool
* @date 2022/11/24
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface UserPerm {
String value() default "";
}
3.自定义SQL方法
如果有额外的自定义SQL,则可以添加。
package com.hongtool.mybatis.perms.enums;
/**
* <p> 自定义本项目支持的SQL方法 </p>
* 模拟MyBatis-plus的 {@link com.baomidou.mybatisplus.core.enums.SqlMethod}
* @author hongtool
* @date 2022/11/1
*/
public enum HongToolSqlMethod {
COUNT_PERMISSION("countPerms", "查询满足条件总记录数(带权限控制)", "<script>\nSELECT COUNT(%s) FROM %s %s %s\n</script>"),
LIST_PERMISSION("listPerms", "查询满足条件所有数据(带权限控制)", "<script>\nSELECT %s FROM %s %s %s\n</script>"),
PAGE_PERMISSION("pagePerms", "查询满足条件所有数据(并翻页)(带权限控制)", "<script>\nSELECT %s FROM %s %s %s\n</script>"),
;
private final String method;
private final String desc;
private final String sql;
HongToolSqlMethod(String method, String desc, String sql) {
this.method = method;
this.desc = desc;
this.sql = sql;
}
public String getMethod() {
return method;
}
public String getDesc() {
return desc;
}
public String getSql() {
return sql;
}
}
4.自定义注入器
package com.hongtool.mybatis.perms.injector;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.hongtool.mybatis.perms.injector.methods.SelectCountPermission;
import com.hongtool.mybatis.perms.injector.methods.SelectListPermission;
import com.hongtool.mybatis.perms.injector.methods.SelectPagePermission;
import java.util.List;
/**
* <p> mybatis 扩展,为了查询有权限的数据 </p>
*
* @author hongtool
* @date 2022/11/1
*/
public class HongToolInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
// 通过权限,查询数据
methodList.add(new SelectListPermission());
methodList.add(new SelectPagePermission());
methodList.add(new SelectCountPermission());
return methodList;
}
}
1)有权限的列表查询
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.hongtool.mybatis.perms.enums.HongToolSqlMethod;
import com.hongtool.mybatis.perms.util.WherePermSqlUtil;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
public class SelectListPermission extends AbstractMethod {
public SelectListPermission() {
super(HongToolSqlMethod.LIST_PERMISSION.getMethod());
}
public SelectListPermission(String methodName) {
super(methodName);
}
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
HongToolSqlMethod sqlMethod = HongToolSqlMethod.LIST_PERMISSION;
String sql = String.format(sqlMethod