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

 本文旨在提供一种实现数据权限控制的思路,整理创建MyBatis拦截器遇到的问题以及解决方式。

1、需求

        要求根据用户配置的角色,在指定的查询接口中加入权限控制,比如:

        系统管理员可查看所有数据;

        部门管理员只能查看本部门的数据;

        一般用户只能查看涉及个人的数据;

2、整体设计

2.1、抽象出1个权限类,封装权限等级、查询条件等相关参数

2.2、解析当前登录的账号信息,创建对应的权限对象,放入ThreadLocal中

2.3、创建一个用于标识需要权限控制的注解,打在MyBatis的Mapper接口的方法上

2.4、自定义一个MyBatis拦截器,拦截含有上述注解的query方法,取到ThreadLocal中的权限,在SQL语句中添加额外的where条件

3、问题以及解决方式

3.1、自定义拦截器建好之后,不生效

        笔者这里是因为依赖的jar中自定义创建了SqlSessionFactory,创建SqlSessionFactory的代码中没有设置拦截器。

        如果项目使用的自定义的SqlSessionFactory,需要创建的时候把拦截器添加进去。

        如下代码:

sqlSessionFactoryBean.setPlugins(new Interceptor[]{MyInterceptor});

可参考这篇文章: springboot配置多数据源后mybatis拦截器失效

       

        如果恰好读者的SqlSessionFactory也是在jar中创建的,或者不能直接修改,则需要另一种方式。

        新建Configuration配置类,配置类中注入SqlSessionFactory集合,遍历SqlSessionFactory手动添加拦截器。需要注意的是,后添加的拦截器先执行。

@Configuration
public class InterceptorConfiguration {
    @Autowired
    private List<SqlSessionFactory> sqlSessionFactoryList;

    @PostConstruct
    public void addInterceptor() {
        for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
            org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();
            //自己添加自定义的拦截器
            configuration.addInterceptor(new MybatisInterceptor());
        }
  
    }

}

3.2、自定义拦截器在PageHelper分页之后才执行

        由于笔者项目中使用了PageHelper,虽然自定义拦截器生效了,但是是在分页之后拦截的。如何让自定义拦截器在PageHelper之前拦截?

        查看PageHelper是如何添加拦截器的,源码如下图:

        通过@AutoConfigureAfter注解指定PageHelper配置类在MybatisAutoConfiguration配置类执行之后再执行。

        参考PageHelper的代码,修改自定义拦截器的配置类,如下:

@Configuration
@AutoConfigureAfter({PageHelperAutoConfiguration.class})
public class InterceptorAutoConfiguration {

    @Autowired
    private List<SqlSessionFactory> sqlSessionFactoryList;

    @PostConstruct
    public void addInterceptor() {
        for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
            org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();
            configuration.addInterceptor(new MybatisInterceptor());
        }
    }
}

       通过@AutoConfigureAfter({PageHelperAutoConfiguration.class})注解,指定自定义的拦截器在PageHelper配置类执行完后再添加。

       在笔者以为大功告成的时候,启动项目,发现还是自定义的配置类先执行。那么问题在哪呢?查阅一番文章后,才知道,@AutoConfigureAfter注解并不是直接加在类上就能用的。

可参考这篇文章具体了解:Spring Boot - 配置排序依赖技巧

        也就是说,如果想用@AutoConfigureAfter,自定义的配置类就不能被Spring Boot的启动类扫描到,并且要在spring.factories文件中配置。

        其中,有两个注意点: 

        1、不让配置类被扫描到,可以将配置类放在一个不被扫描的包下,或者将配置类的@Configuration注解去掉。

        2、spring.factories文件一定要建在META-INF目录下。

最终配置如下

@AutoConfigureAfter({PageHelperAutoConfiguration.class})
public class InterceptorAutoConfiguration {

    @Autowired
    private List<SqlSessionFactory> sqlSessionFactoryList;

    @PostConstruct
    public void addInterceptor() {
        for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
            org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();
            configuration.addInterceptor(new MybatisInterceptor());
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值