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; }