Mybatis拦截器之数据权限过滤与分页集成

需求场景

最近项目有个数据权限的业务需求,要求大致为每个单位只能查看本级单位及下属单位的数据,例如:一个集团军下属十二个旅,那么军级用户可以看到所有数据,而每个旅则只能看到本旅部的数据,以此类推;

解决方案之改SQL

原sql
SELECT
	a.id AS "id",
	a.NAME AS "name",
	a.sex_cd AS "sexCd",
	a.org_id AS "orgId",
	a.STATUS AS "status",
	a.create_org_id AS "createOrgId"
FROM
	pty_person a
WHERE
	a. STATUS = 0

org_id是单位的标识,也就是where条件里再加个单位标识的过滤。

改后sql
SELECT
	a.id AS "id",
	a.NAME AS "name",
	a.sex_cd AS "sexCd",
	a.org_id AS "orgId",
	a.STATUS AS "status",
	a.create_org_id AS "createOrgId"
FROM
	pty_person a
WHERE
	a. STATUS = 0
	and a.org_id LIKE concat(710701070102, '%')

当然通过这个办法也可以实现数据的过滤,但这样的话相比大家也都有同感,那就是每个业务模块 每个人都要进行SQL改动,这次是根据单位过滤、明天又再根据其他的属性过滤,意味着要不停的改来改去,可谓是场面壮观也,而且这种集体改造耗费了时间精力不说,还会有很多不确定因素,比如SQL写错,存在漏网之鱼等等。因此这个解决方案肯定是直接PASS掉咯;

解决方案之拦截器

由于项目大部分采用的持久层框架是Mybatis,也是使用的Mybatis进行分页拦截处理,因此直接采用了Mybatis拦截器实现数据权限过滤。

1、自定义数据权限过滤注解 PermissionAop,负责过滤的开关 

package com.raising.framework.annotation;

import java.lang.annotation.*;

/**
 * 数据权限过滤自定义注解
 * @author lihaoshan
 * @date 2018-07-19
 * */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PermissionAop {

    String value() default "";
}

2、定义全局配置 PermissionConfig 类加载 权限过滤配置文件

package com.raising.framework.config;

import com.raising.utils.PropertiesLoader;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * 全局配置
 * 对应 permission.properties
 * @author lihaoshan
 */
public class PermissionConfig {
    private static Logger logger = LoggerFactory.getLogger(PropertiesLoader.class);

    /**
     * 保存全局属性值
     */
    private static Map<String, String> map = new HashMap<>(16);

    /**
     * 属性文件加载对象
     */
    private static PropertiesLoader loader = new PropertiesLoader(
            "permission.properties");

    /**
     * 获取配置
     */
    public static String getConfig(String key) {
        if(loader == null){
            logger.info("缺失配置文件 - permission.properties");
            return null;
        }
        String value = map.get(key);
        if (value == null) {
            value = loader.getProperty(key);
            map.put(key, value != null ? value : StringUtils.EMPTY);
        }
        return value;
    }

}

3、创建权限过滤的配置文件 permission.properties,用于配置需要拦截的DAO的 namespace

(由于注解@PermissionAop是加在DAO层某个接口上的,而我们分页接口为封装的公共BaseDAO,所以如果仅仅使用注解方式开关拦截的话,会影响到所有的业务模块,因此需要结合额外的配置文件)

# 需要进行拦截的SQL所属namespace
permission.intercept.namespace=com.raising.modules.pty.dao.PtyGroupDao,com.raising.modules.pty.dao.PtyPersonDao

4、自定义权限工具类

根据 StatementHandler 获取Permission注解对象:
package com.raising.utils.permission;

import com.raising.framework.annotation.PermissionAop;
import org.apache.ibatis.mapping.MappedStatement;

import java.lang.reflect.Method;

/**
 * 自定义权限相关工具类
 * @author lihaoshan
 * @date 2018-07-20
 * */
public class PermissionUtils {

    /**
     * 根据 StatementHandler 获取 注解对象
     * @author lihaoshan
     * @date 2018-07-20
     */
    public static PermissionAop getPermissionByDelegate(MappedStatement mappedStatement){
        PermissionAop permissionAop = null;
        try {
            String id = mappedStatement.getId();
            String className = id.substring(0, id.lastIndexOf("."));
            String methodName = id.substring(id.lastIndexOf(".") + 1, id.length());
            final Class cls = Class.forName(className);
            final Method[] method = cls.getMethods();
            for (Method me : method) {
                if (me.getName().equals(methodName) && me.isAnnotationPresent(PermissionAop.class)) {
                    permissionAop = me.getAnnotation(PermissionAop.class);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return permissionAop;
    }
}

5、创建分页拦截器 MybatisSpringPageIntercep

  • 18
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值