基于Mybatis-Plus实现数据权限

这篇具有很好参考价值的文章主要介绍了基于Mybatis-Plus实现数据权限。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概念

数据权限是指对系统用户进行数据资源可见性的控制。实现不同角色登录系统所展示的操作数据范围不一样,达到角色与角色、用户与用户之间数据的隔离。例如:管理员可以看到所有的菜单,而普通用户只能看到部分菜单。在同个表格数据中,管理员可以看到所有用户的数据,而普通用户只能查询到自己的数据。

1.引入依赖

<!-- SpringBoot工程 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>版本自选</version>
</dependency>

2.基本使用

(1).数据权限枚举
import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 数据权限枚举
 *
 * @author baymax
 * @date 2023-02-07 10:41
 */
@AllArgsConstructor
@Getter
public enum DataScope {

    ALL(1, "所有权限"),
    DEPARTMENT(2, "本部门"),
    SELF(3, "仅本人")
    ;

    private final Integer code;
    private final String description;

    public static DataScope findDataScope(Integer code) {
        for (DataScope value : DataScope.values()) {
            if (value.code.equals(code)) {
                return value;
            }
        }
        return null;
    }
}
(2).Mybatis-Plus配置类
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baymax.interceptor.MybatisPlusPermissionInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * mp配置类
 *
 * @author baymax
 * @date 2023-02-07 10:11
 */
@Configuration
public class MybatisPlusConfig {

    /**
     * 添加MP插件到Spring容器中
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
        // 数据权限插件,MybatisPlusPermissionInterceptor需自己实现
        interceptor.addInnerInterceptor(new MybatisPlusPermissionInterceptor());
        return interceptor;
    }
}
(3).Mybatis-Plus拦截器

注意:下面继承的JsqlParserSupport类,是Mybatis-Plus包里已经引入的,这是一个强大的SQL语句解析器,感兴趣的可以去GitHub上看看,地址:https://github.com/JSQLParser/JSqlParser

import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody;
import net.sf.jsqlparser.statement.select.SetOperationList;
import net.sf.jsqlparser.statement.update.Update;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
 * Mybatis-Plus拦截器
 *
 * @author baymax
 * @date 2023-02-08 16:58
 */
public class MybatisPlusPermissionInterceptor extends JsqlParserSupport implements InnerInterceptor {

    /**
     * 数据权限解析器,拼接条件sql,需自己创建的类
     */
    private final MybatisPlusPermissionHandler mybatisPlusPermissionHandler = new MybatisPlusPermissionHandler();

    /**
     * 主要处理查询
     */
    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        // 通过MP插件拿到即将执行的SQL
        PluginUtils.MPBoundSql mp = PluginUtils.mpBoundSql(boundSql);
        // parserSingle方法是JsqlParserSupport父类实现的方法,这里会根据执行的SQL是查询、新增、修改、删除来调用不同的方法,例如:如果是查询,就会调用当前类的processSelect方法
        mp.sql(parserSingle(mp.sql(), ms.getId()));
    }

    /**
     * 操作前置处理,可以在这里改改sql啥的
     */
    @Override
    public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
        InnerInterceptor.super.beforePrepare(sh, connection, transactionTimeout);
    }

    @Override
    protected void processDelete(Delete delete, int index, String sql, Object obj) {
        super.processDelete(delete, index, sql, obj);
    }

    @Override
    protected void processUpdate(Update update, int index, String sql, Object obj) {
        super.processUpdate(update, index, sql, obj);
    }

    @Override
    protected void processSelect(Select select, int index, String sql, Object obj) {
        SelectBody selectBody = select.getSelectBody();
        try {
            // 单个sql
            if (selectBody instanceof PlainSelect) {
                this.setWhere((PlainSelect) selectBody, obj.toString());
            } else if (selectBody instanceof SetOperationList) {
                // 多个sql,用;号隔开,一般不会用到。例如:select * from user;select * from role;
                SetOperationList setOperationList = (SetOperationList) selectBody;
                List<SelectBody> selects = setOperationList.getSelects();
                selects.forEach(s -> this.setWhere((PlainSelect) s, obj.toString()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    protected void setWhere(PlainSelect plainSelect, String mapperId) {
        Expression sqlSegment = mybatisPlusPermissionHandler.getSqlSegment(plainSelect.getWhere(), mapperId);
        if (null != sqlSegment) {
            plainSelect.setWhere(sqlSegment);
        }
    }
(4).Mybatis-Plus处理器

这里就是处理数据权限的主要类,来动态拼接sql的条件,达到数据隔离的效果

import com.baymax.enums.DataScope;
import com.baymax.utils.SecurityUserUtils;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;

/**
 * 数据权限处理器
 *
 * @author baymax
 * @date 2023-02-09 15:50
 */
public class MybatisPlusPermissionHandler {

    /**
     * 拼接数据权限sql的条件
     *
     * @param where sql语句的where条件
     * @param mapperId mapper执行的方法
     */
    public Expression getSqlSegment(Expression where, String mapperId) {
        //TODO 如果是管理员,拥有全部数据权限,不做任何条件语句的拼接,直接返回未处理的where
        if(管理员) {
            return where;
        }
        //TODO mapperId=类路径 + 方法。例如:com.xxx.UserMapper.selectList()
        // 结合自定义注解,通过反射的方式拿到方法上的注解。例如联查SQL,需要指定(别名.数据权限字段)拼接到where后面
        // if("判断mapperId执行方法上是否有注解") {
        //     "拿到value后,传入下面的buildDataFilter()方法里做条件拼接"
        // }
        
        // 构建查询条件
        String sql = buildDataFilter();
        if ("".equals(sql)) {
            return where;
        }
        try {
            Expression expression = CCJSqlParserUtil.parseExpression(sql);
            // 数据权限使用单独的括号 防止与其他条件冲突
            Parenthesis parenthesis = new Parenthesis(expression);
            if (null != where) {
                return new AndExpression(where, parenthesis);
            } else {
                return parenthesis;
            }
        } catch (Exception e) {
            throw new RuntimeException("数据权限解析异常 => " + e.getMessage());
        }
    }

    /**
     * 非常重要!!!
     * 拼接数据权限sql的条件,比如在我们登录成功时,会把用户、角色、数据权限信息缓存到容器上下文或者redis中,当非管理员用户访问某个接口时有查询一些数据,最后会到这个来,这时候我们可以从容器上下文或redis中拿到当前用户的信息,判断用户的数据权限,不同数据权限走不同的拼接SQL
     */
    private String buildDataFilter() {
        StringBuilder stringBuilder = new StringBuilder();
        DataScope dataScope = "拿当前用户的数据权限";
        // 部门数据权限
        if (DataScope.DEPARTMENT == dataScope) {
            // 例如:可以返回 "department_id IN (当前用户所属的部门id)"
            return "";
        } else if (DataScope.SELF == dataScope) {
            // 仅本人数据权限,create_by字段是表中的字段,这里不一定是这个字段,根据自己需求在需要做数据权限的表加上自定义得字段
            stringBuilder.append(" create_by").append("= '").append("拿当前用户的username").append("'");
            return stringBuilder.toString();
        }
        return "";
    }

注意:这里省略了登录的流程,这个自行实现

3.测试

当前登录的用户为:zzh

(1).即将查询的表数据

mybatisplus 数据权限,JAVA,java,spring boot,mybatis

(2).查询的结果

mybatisplus 数据权限,JAVA,java,spring boot,mybatis文章来源地址https://www.toymoban.com/news/detail-688145.html

到了这里,关于基于Mybatis-Plus实现数据权限的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Spring Boot + MyBatis-Plus实现数据库读写分离

    Spring Boot + MyBatis-Plus实现数据库读写分离

    🎉Spring Boot + MyBatis-Plus实现数据库读写分离 ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹 ✨博客主页:IT·陈寒的博客 🎈该系列文章专栏:架构设计 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习 🍹文章作者技术和水平有限,如果文中出现错误,希望

    2024年02月05日
    浏览(18)
  • SpringBoot整合Mybatis-Plus+Druid实现多数据源

    SpringBoot整合Mybatis-Plus+Druid实现多数据源

    🌺本文主要讲解 springboot +mybatisplus + druid 实现多数据源配置功能 🌺 主页传送门:📀 传送 Spring Boot:    Spring Boot是一个基于Spring框架的开源Java开发框架,旨在简化Spring应用程序的开发、配置和部署。它提供了一种快速、敏捷的方式来构建独立的、生产级别的Spring应用程

    2024年02月09日
    浏览(10)
  • 利用 Mybatis-Plus 的动态数据源实现多数据源配置

    利用 Mybatis-Plus 的动态数据源实现多数据源配置

    目录 一、导入依赖 二、Application.yaml配置文件 三、切换数据源 四、其他方法 4.1 配置多个数据源 4.2 定义Datasource和EntityManager 4.3 在需要使用数据源的地方注入不同的EntityManager 官网:https://baomidou.com/pages/a61e1b/#dynamic-datasource 默认是使用配置文件中master参数设置的数据库。

    2024年02月13日
    浏览(14)
  • springBoot + mybatis-plus 实现监听 mysql的数据增删改的监听

    在Spring Boot + MyBatis-Plus中实现MySQL数据增删改的监听,可以通过以下步骤: 1. 添加MyBatis-Plus依赖,在pom.xml文件中添加以下依赖:   2. 配置MyBatis-Plus,通常在application.yml文件中进行配置: 3. 创建监听器类,实现com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor接口。  4. 在My

    2024年02月15日
    浏览(65)
  • Spring Boot + MyBatis-Plus 实现 MySQL 主从复制动态数据源切换

    Spring Boot + MyBatis-Plus 实现 MySQL 主从复制动态数据源切换

    MySQL 主从复制是一种常见的数据库架构,它可以提高数据库的性能和可用性。 动态数据源切换则可以根据业务需求,在不同场景下使用不同的数据源,比如在读多写少的场景下,可以通过切换到从库来分担主库的压力 。 在本文中,我们将介绍如何在 Spring Boot 中实现 MySQL 动

    2024年02月19日
    浏览(13)
  • MyBatis Plus 拦截器实现数据权限控制

    MyBatis Plus 拦截器实现数据权限控制

    上篇文章介绍的MyBatis Plus 插件实际上就是用拦截器实现的,MyBatis Plus拦截器对MyBatis的拦截器进行了包装处理,操作起来更加方便 2.1、InnerInterceptor MyBatis Plus提供的InnerInterceptor接口提供了如下方法,主要包括:在查询之前执行,在更新之前执行,在SQL准备之前执行 2.2、编写简

    2024年01月17日
    浏览(10)
  • Java:mybatis-plus-generator-ui 基于Mybatis-Plus的代码自助生成器

    Java:mybatis-plus-generator-ui 基于Mybatis-Plus的代码自助生成器

    引用官方文档上的简介: 提供交互式的Web UI用于生成兼容mybatis-plus框架的相关功能代码,包括Entity,Mapper,Mapper.xml,Service,Controller等 ,可以自定义模板以及各类输出参数,也可通过SQL查询语句直接生成代码。 文档 github: https://github.com/davidfantasy/mybatis-plus-generator-ui gitee: https://g

    2024年02月10日
    浏览(8)
  • mybatis-plus配置日志实现方式

    Mybatis-plus是一个基于Mybatis的强大框架,可以帮助开发者快速地开发高质量的数据库应用程序。Mybatis-plus提供了许多配置项,其中一个重要的配置项是log-impl。 log-impl配置项定义了Mybatis-plus的日志实现方式,有两种可选的方式: SLF4J日志实现 如果你的项目已经使用了SLF4J日志框

    2024年02月09日
    浏览(5)
  • spring boot集成mybatis-plus——Mybatis Plus 查询数据(图文讲解)

    spring boot集成mybatis-plus——Mybatis Plus 查询数据(图文讲解)

     更新时间 2023-01-03 16:07:12 大家好,我是小哈。 本小节中,我们将学习如何通过 Mybatis Plus 查询数据库表中的数据。 在前面小节中,我们已经定义好了一个用于测试的用户表, 执行脚本如下: 定义一个名为  User  实体类: 不明白 Mybatis Plus 实体类注解的小伙伴,可参考前面

    2024年02月02日
    浏览(9)
  • Mybatis-plus动态数据源

    Mybatis-plus动态数据源

    由于服务没有做微服务部署,需要在后台管理系统访问其他服务的库,所以需要用到动态数据源切换 引入依赖 mybatis-plus动态数据源依赖 更改配置 配置类 添加注解 @DS注解我一般放在dao层,因为觉得这样更合理 启动测试 问题: 动态数据源切换时效 当服务层接口添加事务注解

    2024年04月12日
    浏览(20)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包