MybatisPlus 实现数据拦截

基于配置文件实现(关键key存储在配置文件,通过读取配置文件来实现动态拼接sql)

1、创建注解类

@UserDataPermission(id="app")

注:id用以区分是小程序还是应用程序

注解加的位置:

2、配置枚举类配置文件 EDataPermissionType

 

3、创建拦截器重写InnerInterceptor接口,重写查询方法

/**
 * 拦截器
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class MyDataPermissionInterceptor extends JsqlParserSupport implements InnerInterceptor {
    /**
     * 数据权限处理器
     */
    private MyDataPermissionHandler dataPermissionHandler;
 
    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) {
            return;
        }
        PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
        mpBs.sql(this.parserSingle(mpBs.sql(), ms.getId()));
    }
 
    @Override
    protected void processSelect(Select select, int index, String sql, Object obj) {
        SelectBody selectBody = select.getSelectBody();
        if (selectBody instanceof PlainSelect) {
            this.setWhere((PlainSelect) selectBody, (String) obj);
        } else if (selectBody instanceof SetOperationList) {
            SetOperationList setOperationList = (SetOperationList) selectBody;
            List<SelectBody> selectBodyList = setOperationList.getSelects();
            selectBodyList.forEach(s -> this.setWhere((PlainSelect) s, (String) obj));
        }
    }
 /**
     * 设置 where 条件
     *
     * @param plainSelect  查询对象
     * @param whereSegment 查询条件片段
     */
    private void setWhere(PlainSelect plainSelect, String whereSegment) {
 
        Expression sqlSegment = this.dataPermissionHandler.getSqlSegment(plainSelect, whereSegment);
        if (null != sqlSegment) {
            plainSelect.setWhere(sqlSegment);
        }
    }
}

4、创建处理类,动态拼接sql片段,设置where

/**
 * 拦截器处理器
 */
@Slf4j
public class MyDataPermissionHandler {
    private ISysUserDataRelationService sysUserDataRelationService = new SysUserDataRelationServiceImpl();
    private MpcTokenUtil mpcTokenUtil = new MpcTokenUtil();
    private AppManageConfig appManageConfig;
 
    /**
     * 获取数据权限 SQL 片段
     *
     * @param plainSelect  查询对象
     * @param whereSegment 查询条件片段
     * @return JSqlParser 条件表达式
     */
    @SneakyThrows(Exception.class)
    public Expression getSqlSegment(PlainSelect plainSelect, String whereSegment) {
        sysUserDataRelationService = SpringUtils.getBean(ISysUserDataRelationService.class);
        mpcTokenUtil = SpringUtils.getBean(MpcTokenUtil.class);
        appManageConfig = SpringUtils.getBean(AppManageConfig.class);
        // 待执行 SQL Where 条件表达式
        Expression where = plainSelect.getWhere();
        if (where == null) {
            where = new HexValue(" 1 = 1 ");
        }
        //获取mapper名称
        String className = whereSegment.substring(0, whereSegment.lastIndexOf("."));
        //获取方法名
        String methodName = whereSegment.substring(whereSegment.lastIndexOf(".") + 1);
        Table fromItem = (Table) plainSelect.getFromItem();
        // 有别名用别名,无别名用表名,防止字段冲突报错
        Alias fromItemAlias = fromItem.getAlias();
        String mainTableName = fromItemAlias == null ? fromItem.getName() : fromItemAlias.getName();
        //获取当前mapper 的方法
        Method[] methods = Class.forName(className).getMethods();
        //遍历判断mapper 的所有方法,判断方法上是否有 UserDataPermission
        for (Method m : methods) {
            if (Objects.equals(m.getName(), methodName)) {
                UserDataPermission annotation = m.getAnnotation(UserDataPermission.class);
                if (annotation == null) {
                    return where;
                }
                String type = annotation.id();
                //小程序或应用程序的集合,in的范围
                List<String> dataIds = sysUserDataRelationService.getUserPermission(mpcTokenUtil.getUserAccountByToken(), EDataPermissionType.getCode(type));
                if (CollectionUtils.isEmpty(dataIds)) {
                    return null;
                }
                log.info("开始进行权限过滤,where: {},mappedStatementId: {}", where, whereSegment);
                // 把集合转变为JSQLParser需要的元素列表
                ItemsList ids = new ExpressionList(dataIds.stream().map(StringValue::new).collect(Collectors.toList()));
                //in表达式的写法
                InExpression inExpressiondept = null;
                String key = appManageConfig.getList().get(type);
                inExpressiondept = new InExpression(new Column(mainTableName + "." + key), ids);
                return new AndExpression(where, inExpressiondept);
                
            }
        }
        //说明无权查看,
        where = new HexValue(" 1 = 2 ");
        return where;
    }
 
}

5、将拦截器加到mybatis-plus插件中

@Configuration
@MapperScan("com.shinho.mpc.mapper")
public class MybatisPlusConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
 
    /**
     * 将拦截器加到mybatis插件中
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加数据权限插件
        MyDataPermissionInterceptor dataPermissionInterceptor = new MyDataPermissionInterceptor();
        // 添加自定义的数据权限处理器
        dataPermissionInterceptor.setDataPermissionHandler(new MyDataPermissionHandler());
        interceptor.addInnerInterceptor(dataPermissionInterceptor);
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
 
}

6、使用的位置加注解即可生效

在mapper层加上注解:

@UserDataPermission(id="app")

id :注解入参

app:应用程序类型权限控制

mp:小程序类型权限控制

7、数据拦截效果:

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis-Plus本身并不直接提供数据脱敏的功能,但可以通过自定义SQL语句和插件来实现数据脱敏。 一种常见的方法是使用数据库的内置函数或自定义函数来对敏感字段进行脱敏处理。你可以在SQL语句中使用这些函数,例如使用MySQL的`SUBSTRING`或`REPLACE`函数来截取或替换字段的部分内容。 另一种方法是通过MyBatis-Plus的拦截器机制来实现数据脱敏。你可以创建一个自定义的拦截器,在查询数据库之前或之后对结果进行处理。在拦截器中,你可以访问到返回的结果对象,然后对敏感字段进行处理,例如将手机号码中的中间几位替换为星号。 以下是一个简单的示例,展示了如何通过自定义拦截器实现数据脱敏: ```java @Intercepts({ @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}) }) public class DataDesensitizationInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { Object result = invocation.proceed(); // 对返回结果进行处理,例如将手机号码进行脱敏 if (result instanceof List) { List<?> resultList = (List<?>) result; for (Object obj : resultList) { if (obj instanceof User) { User user = (User) obj; user.setPhone(desensitizePhoneNumber(user.getPhone())); } } } return result; } private String desensitizePhoneNumber(String phoneNumber) { // 实现自己的脱敏逻辑,例如将中间四位替换为星号 return phoneNumber.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"); } // 省略其他方法实现... } ``` 在以上示例中,我们创建了一个拦截器 `DataDesensitizationInterceptor`,并在 `intercept` 方法中对查询结果进行了脱敏处理。你可以根据自己的需求以及具体的数据脱敏规则进行定制化开发。 最后,记得在MyBatis的配置文件中配置该拦截器: ```xml <configuration> <!-- 其他配置项 --> <plugins> <plugin interceptor="com.example.DataDesensitizationInterceptor"/> </plugins> </configuration> ``` 这样,当执行查询操作时,拦截器将会被触发,从而实现数据脱敏的效果。当然,你可以根据具体需求和场景进行更复杂的数据脱敏操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值