Mybatis-plus 數據權限


一、MyBatisPlusConfig配置:

package com.ruoyi.framework.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.ruoyi.framework.datascope.DataScopeInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * Mybatis Plus 配置
 *
 * @author ruoyi
 */
@EnableTransactionManagement(proxyTargetClass = true)
@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        // 數據權限
        interceptor.addInnerInterceptor(dataScopeInterceptor());
        // 分頁插件
        interceptor.addInnerInterceptor(paginationInnerInterceptor());
        // 樂觀鎖插件
        interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());

        return interceptor;
    }

    /**
     * 分頁插件,自動識別數據庫類型
     */
    public PaginationInnerInterceptor paginationInnerInterceptor() {
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        // 設置數據庫類型為mysql
        paginationInnerInterceptor.setDbType(DbType.MYSQL);
        // 設置最大單頁限制數量,默認 500 條,-1 不受限制
        paginationInnerInterceptor.setMaxLimit(-1L);
        return paginationInnerInterceptor;
    }

    /**
     * 樂觀鎖插件
     */
    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
        return new OptimisticLockerInnerInterceptor();
    }

    /**
     * 數據權限插件
     *
     * @return DataScopeInterceptor
     */
    public DataScopeInterceptor dataScopeInterceptor() {
        return new DataScopeInterceptor();
    }
}

 二、DataScopeInnerInterceptor數據權限攔截器配置

package com.ruoyi.framework.datascope;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.ruoyi.common.Enum.DataScopeTypeEnum;
import com.ruoyi.common.core.data.DataScope;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.web.service.TokenService;
import org.apache.ibatis.executor.Executor;
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.util.List;
import java.util.Map;

/**
 * 數據權限
 *
 * @author: Fred
 * @email 453086@qq.com
 * @create: 2021-05-25 11:12
 */
public class DataScopeInterceptor implements InnerInterceptor {

    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds,
                            ResultHandler resultHandler, BoundSql boundSql) {

        PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
        String originalSql = boundSql.getSql();
        Object parameterObject = boundSql.getParameterObject();

        // 查找參數中包含DataScope類型的參數
        DataScope dataScope = findDataScopeObject(parameterObject);
        if (dataScope == null) {
            return;
        }

        LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
        if (StringUtils.isNotNull(loginUser)) {
            SysUser currentUser = loginUser.getUser();
            // 如果是超級管理員,則不過濾數據
            if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) {
                String scopeName = dataScope.getScopeName();
                List<String> deptIds = dataScope.getDeptIds();

                dataScopeFilter(currentUser, deptIds);
                if (deptIds.isEmpty()) {
                    originalSql = String.format("SELECT %s FROM (%s) temp_data_scope WHERE 1 = 2",
                            dataScope.getFunc().getType(), originalSql);
                } else {
                    String join = CollectionUtil.join(deptIds, ",");
                    originalSql = String.format("SELECT %s FROM (%s) temp_data_scope WHERE temp_data_scope.%s IN (%s)",
                            dataScope.getFunc().getType(), originalSql, scopeName, join);
                }
            }
        }
        mpBs.sql(originalSql);
    }

    /**
     * 查找參數是否包括DataScope對象
     *
     * @param parameterObj 參數列表
     * @return DataScope
     */
    private DataScope findDataScopeObject(Object parameterObj) {
        if (parameterObj instanceof DataScope) {
            return (DataScope) parameterObj;
        } else if (parameterObj instanceof Map) {
            for (Object val : ((Map<?, ?>) parameterObj).values()) {
                if (val instanceof DataScope) {
                    return (DataScope) val;
                }
            }
        }
        return null;
    }

    /**
     * 數據范圍
     *
     * @return
     */
    private void dataScopeFilter(SysUser user, List<String> deptList) {

        for (SysRole role : user.getRoles()) {
            String roleScope = role.getDataScope();
            if (DataScopeTypeEnum.ALL.getType().equals(roleScope)) {
                return;
            }
            if (DataScopeTypeEnum.CUSTOM.getType().equals(roleScope)) {
                //   獲取自定義
            }
            if (DataScopeTypeEnum.OWN_CHILD_LEVEL.getType().equals(roleScope)) {
                // 獲取子集
            }
            if (DataScopeTypeEnum.OWN_LEVEL.getType().equals(roleScope)) {
                deptList.add(user.getDeptId().toString());
            }
        }
    }
}
/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */

package com.ruoyi.common.core.data;

import com.ruoyi.common.Enum.DataScopeFuncEnum;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author lengleng
 * @date 2018/8/30
 * 數據權限查詢參數
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class DataScope extends HashMap {

    /**
     * 限制范圍的字段名稱
     */
    private String scopeName = "dept_id";

    /**
     * 具體的數據范圍
     */
    private List<String> deptIds = new ArrayList<>();

    /**
     * 是否只查詢本部門
     */
    private Boolean isOnly = false;

    /**
     * 函數名稱,默認 SELECT * ;
     *
     * <ul>
     * <li>COUNT(1)</li>
     * </ul>
     */
    private DataScopeFuncEnum func = DataScopeFuncEnum.ALL;
}
/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */

package com.ruoyi.common.Enum;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 數據權限函數類型
 *
 * @author lengleng
 * @date 2020-06-17
 */
@Getter
@AllArgsConstructor
public enum DataScopeFuncEnum {

    /**
     * 查詢全部數據 SELECT * FROM (originSql) temp_data_scope WHERE temp_data_scope.dept_id IN
     * (1)
     */
    ALL("*", "全部"),

    /**
     * 查詢函數COUNT SELECT COUNT(1) FROM (originSql) temp_data_scope WHERE
     * temp_data_scope.dept_id IN (1)
     */
    COUNT("COUNT(1)", "自定義");

    /**
     * 類型
     */
    private final String type;

    /**
     * 描述
     */
    private final String description;

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM