依赖jar包
引入包 |
版本 |
jdk |
1.8 |
spring boot |
2.7.2 |
mybatis-plus-extension |
3.5.3.1 |
mybatis-plus |
3.5.3.1 |
mybatis-plus-boot-starter |
3.5.3.1 |
spring-boot-starter-web |
2.7.9 |
使用
添加依赖
1 2 3 4 5
| <dependency> <groupId>cn.allbs</groupId> <artifactId>allbs-mybatis</artifactId> <version>2.0.3</version> </dependency>
|
1
| implementation 'cn.allbs:allbs-mybatis:2.0.3'
|
1
| implementation("cn.allbs:allbs-mybatis:2.0.3")
|
配置示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| mybatis-plus: mapper-locations: classpath*:mapper/*/*.xml global-config: banner: false db-config: id-type: auto logic-delete-value: 1 logic-not-delete-value: 0
type-handlers-package: com.allbs.allbsjwt.config.handler show-sql: true meta-custom: del-flg: delFlag create-name: createId update-name: updateId chine-rate: 1.5 data-pms: true
|
日志打印示例
审计字段自动插入
权限过滤
开启
mybatis-plus.data-pms 设置为true
,看上方配置示例最后一个配置
使用说明
实现DataPmsHandler
后写详细的逻辑即可,比如:
@ScopeField
是用于跟表关联的实体类上的注解,用于标记改表中权限过滤的字段是哪个,以下类举例:下文中DEFAULT_FILTER_FIELD
默认的是ent_id
指数据库表中以该字段作为区分,如果有张表突然设置的是unit_id
而不是ent_id
则在对应的实体上设置@ScopeField("unit_id")
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
| import cn.allbs.allbsjwt.config.utils.SecurityUtils; import cn.allbs.allbsjwt.config.vo.SysUser; import cn.allbs.common.constant.StringPool; import cn.allbs.mybatis.datascope.DataPmsHandler; import cn.allbs.mybatis.datascope.ScopeField; import cn.allbs.mybatis.utils.PluginUtils; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import lombok.extern.slf4j.Slf4j; import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.operators.conditional.AndExpression; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; import net.sf.jsqlparser.expression.operators.relational.InExpression; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; import org.springframework.stereotype.Component;
import java.util.Optional; import java.util.Set;
@Slf4j @Component public class CustomPermissionHandler implements DataPmsHandler {
private final static String DEFAULT_FILTER_FIELD = "ent_id";
@Override public Expression getSqlSegment(final Table table, Expression where, String mappedStatementId) {
SysUser sysUser = SecurityUtils.getUser(); if (sysUser == null) { return where; } Set<Long> permissionEntList = sysUser.getEntIdList();
TableInfo tableInfo = TableInfoHelper.getTableInfo(table.getName()); String fieldName = Optional.ofNullable(tableInfo.getEntityType().getAnnotation(ScopeField.class)).map(ScopeField::value).orElse(DEFAULT_FILTER_FIELD); String finalFieldName = Optional.of(table).map(Table::getAlias).map(a -> a.getName() + StringPool.DOT + fieldName).orElse(fieldName);
if (permissionEntList.size() > 1) { InExpression inExpression = new InExpression(new Column(finalFieldName), PluginUtils.getItemList(permissionEntList));
return where == null ? inExpression : new AndExpression(where, inExpression); } EqualsTo equalsTo = new EqualsTo(); equalsTo.setLeftExpression(new Column(finalFieldName)); equalsTo.setRightExpression(new LongValue(permissionEntList.stream().findFirst().orElse(0L))); return where == null ? equalsTo : new AndExpression(where, equalsTo); } }
|
效果
忽略权限拦截的方法
在对应的dao指定方法上添加注解@InterceptorIgnore
- 使用mybatis plus 内置sdk的情况下忽略:
dao继承的BaseMapper修改为PmsMapper
新增、修改、批量新增、批量修改时的越权判断
实现DataPmsHandler
中的updateParameter
和insertParameter
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
| package cn.allbs.allbsjwt.config.datascope.mapper;
import cn.allbs.allbsjwt.config.exception.UserOverreachException; import cn.allbs.allbsjwt.config.utils.SecurityUtils; import cn.allbs.allbsjwt.config.vo.SysUser; import cn.allbs.common.constant.StringPool; import cn.allbs.mybatis.datascope.DataPmsHandler; import cn.allbs.mybatis.datascope.ScopeField; import cn.allbs.mybatis.utils.PluginUtils; import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; import lombok.extern.slf4j.Slf4j; import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.operators.conditional.AndExpression; import net.sf.jsqlparser.expression.operators.relational.EqualsTo; import net.sf.jsqlparser.expression.operators.relational.InExpression; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.insert.Insert; import net.sf.jsqlparser.statement.update.Update; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.ParameterMapping; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; import org.springframework.stereotype.Component;
import java.util.List; import java.util.Optional; import java.util.Set;
@Slf4j @Component public class CustomPermissionHandler implements DataPmsHandler {
private final static String DEFAULT_FILTER_FIELD = "ent_id";
@Override public Expression getSqlSegment(final Table table, Expression where, String mappedStatementId) {
SysUser sysUser = SecurityUtils.getUser(); if (sysUser == null) { return where; } Set<Long> permissionEntList = sysUser.getEntIdList();
TableInfo tableInfo = TableInfoHelper.getTableInfo(table.getName()); String fieldName = tableInfo.getFieldList().stream() .filter(a -> a.getField().getAnnotation(ScopeField.class) != null) .map(a -> a.getField().getAnnotation(ScopeField.class).value()) .findFirst() .orElse(DEFAULT_FILTER_FIELD); Alias fromItemAlias = table.getAlias(); String finalFieldName = Optional.ofNullable(fromItemAlias).map(a -> a.getName() + StringPool.DOT + fieldName).orElse(fieldName);
if (permissionEntList.size() > 1) { InExpression inExpression = new InExpression(new Column(finalFieldName), PluginUtils.getItemList(permissionEntList));
return where == null ? inExpression : new AndExpression(where, inExpression); } EqualsTo equalsTo = new EqualsTo(); equalsTo.setLeftExpression(new Column(finalFieldName)); equalsTo.setRightExpression(new LongValue(permissionEntList.stream().findFirst().orElse(0L))); return where == null ? equalsTo : new AndExpression(where, equalsTo); }
@Override public void updateParameter(Update updateStmt, MappedStatement mappedStatement, BoundSql boundSql) { TableInfo tableInfo = TableInfoHelper.getTableInfo(updateStmt.getTable().getName()); parameterHandler(tableInfo.getFieldList(), boundSql); }
@Override public void insertParameter(Insert insertStmt, BoundSql boundSql) { TableInfo tableInfo = TableInfoHelper.getTableInfo(insertStmt.getTable().getName()); parameterHandler(tableInfo.getFieldList(), boundSql); }
private void parameterHandler(List<TableFieldInfo> fieldList, BoundSql boundSql) { SysUser sysUser = SecurityUtils.getUser(); if (sysUser.getId() == 1L) { return; } Set<Long> permissionEntList = sysUser.getEntIdList();
String fieldName = fieldList.stream() .filter(a -> a.getField().getAnnotation(ScopeField.class) != null) .map(a -> a.getField().getAnnotation(ScopeField.class).value()) .findFirst() .orElse(DEFAULT_FILTER_FIELD);
MetaObject metaObject = SystemMetaObject.forObject(boundSql.getParameterObject());
for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) { String propertyName = parameterMapping.getProperty(); if (propertyName.startsWith("ew.paramNameValuePairs")) { continue; } String[] arr = propertyName.split("\\."); String propertyNameTrim = arr[arr.length - 1].replace("_", "").toUpperCase(); if (fieldName.replaceAll("[._\\-$]", "").toUpperCase().equals(propertyNameTrim)) { if (!Optional.ofNullable(metaObject.getValue(propertyName)).isPresent()) { return; } long currentEntId = Long.parseLong(metaObject.getValue(propertyName).toString()); if (permissionEntList.contains(currentEntId)) { metaObject.setValue(propertyName, currentEntId); } else { throw new UserOverreachException(); } }
} } }
|
源码
github