update [重大更新] 重写数据权限实现

This commit is contained in:
疯狂的狮子li 2021-12-07 21:31:55 +08:00
parent ede47929ff
commit 3d47e951be
21 changed files with 409 additions and 184 deletions

View File

@ -25,6 +25,7 @@
<poi.version>4.1.2</poi.version> <poi.version>4.1.2</poi.version>
<easyexcel.version>2.2.11</easyexcel.version> <easyexcel.version>2.2.11</easyexcel.version>
<cglib.version>3.3.0</cglib.version> <cglib.version>3.3.0</cglib.version>
<common-text.version>1.9</common-text.version>
<velocity.version>2.3</velocity.version> <velocity.version>2.3</velocity.version>
<mybatis-plus.version>3.4.3.4</mybatis-plus.version> <mybatis-plus.version>3.4.3.4</mybatis-plus.version>
<p6spy.version>3.9.1</p6spy.version> <p6spy.version>3.9.1</p6spy.version>
@ -121,6 +122,12 @@
<version>${cglib.version}</version> <version>${cglib.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>${common-text.version}</version>
</dependency>
<!-- velocity代码生成使用模板 --> <!-- velocity代码生成使用模板 -->
<dependency> <dependency>
<groupId>org.apache.velocity</groupId> <groupId>org.apache.velocity</groupId>

View File

@ -47,6 +47,11 @@
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
</dependency>
<!-- JSON工具类 --> <!-- JSON工具类 -->
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>

View File

@ -14,15 +14,11 @@ public @interface DataScope {
/** /**
* 部门表的别名 * 部门表的别名
*/ */
String deptAlias() default ""; String deptName() default "";
/** /**
* 用户表的别名 * 用户表的别名
*/ */
String userAlias() default ""; String userName() default "";
/**
* 是否过滤用户权限
*/
boolean isUser() default false;
} }

View File

@ -0,0 +1,61 @@
package com.ruoyi.common.enums;
import com.ruoyi.common.utils.StringUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 数据权限类型
*
* 语法支持 spel 模板表达式
*
* @author Lion Li
*/
@Getter
@AllArgsConstructor
public enum DataScopeType {
/**
* 全部数据权限
*/
DATA_SCOPE_ALL("1", ""),
/**
* 自定数据权限
*/
DATA_SCOPE_CUSTOM("2", " OR #{#deptName} IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = #{#roleId} ) "),
/**
* 部门数据权限
*/
DATA_SCOPE_DEPT("3", " OR #{#deptName} = #{#deptId} "),
/**
* 部门及以下数据权限
*/
DATA_SCOPE_DEPT_AND_CHILD("4", " OR #{#deptName} IN ( SELECT dept_id FROM sys_dept WHERE dept_id = #{#deptId} OR find_in_set( #{#deptId} , ancestors ) )"),
/**
* 仅本人数据权限
*/
DATA_SCOPE_SELF("5", " OR #{#userName?:1} = #{#userId?:0} ");
private final String code;
/**
* 语法 采用 spel 模板表达式
*/
private final String sql;
public static DataScopeType findCode(String code) {
if (StringUtils.isBlank(code)) {
return null;
}
for (DataScopeType type : values()) {
if (type.getCode().equals(code)) {
return type;
}
}
return null;
}
}

View File

@ -1,12 +1,17 @@
package com.ruoyi.demo.mapper; package com.ruoyi.demo.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus; import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
import com.ruoyi.demo.domain.TestDemo; import com.ruoyi.demo.domain.TestDemo;
import com.ruoyi.demo.domain.vo.TestDemoVo; import com.ruoyi.demo.domain.vo.TestDemoVo;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.List;
/** /**
* 测试单表Mapper接口 * 测试单表Mapper接口
* *
@ -15,6 +20,14 @@ import org.apache.ibatis.annotations.Param;
*/ */
public interface TestDemoMapper extends BaseMapperPlus<TestDemo> { public interface TestDemoMapper extends BaseMapperPlus<TestDemo> {
@DataScope(deptName = "dept_id", userName = "user_id")
Page<TestDemoVo> customPageList(@Param("page") Page<TestDemo> page, @Param("ew") Wrapper<TestDemo> wrapper); Page<TestDemoVo> customPageList(@Param("page") Page<TestDemo> page, @Param("ew") Wrapper<TestDemo> wrapper);
@Override
@DataScope(deptName = "dept_id", userName = "user_id")
<P extends IPage<TestDemo>> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper<TestDemo> queryWrapper);
@Override
@DataScope(deptName = "dept_id", userName = "user_id")
List<TestDemo> selectList(@Param(Constants.WRAPPER) Wrapper<TestDemo> queryWrapper);
} }

View File

@ -1,7 +1,13 @@
package com.ruoyi.demo.mapper; package com.ruoyi.demo.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus; import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
import com.ruoyi.demo.domain.TestTree; import com.ruoyi.demo.domain.TestTree;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/** /**
* 测试树表Mapper接口 * 测试树表Mapper接口
@ -11,4 +17,7 @@ import com.ruoyi.demo.domain.TestTree;
*/ */
public interface TestTreeMapper extends BaseMapperPlus<TestTree> { public interface TestTreeMapper extends BaseMapperPlus<TestTree> {
@Override
@DataScope(deptName = "dept_id", userName = "user_id")
List<TestTree> selectList(@Param(Constants.WRAPPER) Wrapper<TestTree> queryWrapper);
} }

View File

@ -1,16 +1,15 @@
package com.ruoyi.demo.service.impl; package com.ruoyi.demo.service.impl;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.annotation.DataScope; import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl; import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.core.page.PagePlus; import com.ruoyi.common.core.page.PagePlus;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.PageUtils; import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.demo.domain.TestDemo; import com.ruoyi.demo.domain.TestDemo;
import com.ruoyi.demo.domain.bo.TestDemoBo; import com.ruoyi.demo.domain.bo.TestDemoBo;
import com.ruoyi.demo.domain.vo.TestDemoVo; import com.ruoyi.demo.domain.vo.TestDemoVo;
@ -36,7 +35,6 @@ public class TestDemoServiceImpl extends ServicePlusImpl<TestDemoMapper, TestDem
return getVoById(id); return getVoById(id);
} }
@DataScope(isUser = true)
@Override @Override
public TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo, PageQuery pageQuery) { public TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo); LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo);
@ -47,7 +45,6 @@ public class TestDemoServiceImpl extends ServicePlusImpl<TestDemoMapper, TestDem
/** /**
* 自定义分页查询 * 自定义分页查询
*/ */
@DataScope(isUser = true)
@Override @Override
public TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo, PageQuery pageQuery) { public TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo); LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo);
@ -55,7 +52,6 @@ public class TestDemoServiceImpl extends ServicePlusImpl<TestDemoMapper, TestDem
return PageUtils.buildDataInfo(result); return PageUtils.buildDataInfo(result);
} }
@DataScope(isUser = true)
@Override @Override
public List<TestDemoVo> queryList(TestDemoBo bo) { public List<TestDemoVo> queryList(TestDemoBo bo) {
return listVo(buildQueryWrapper(bo)); return listVo(buildQueryWrapper(bo));

View File

@ -3,7 +3,6 @@ package com.ruoyi.demo.service.impl;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl; import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.demo.domain.TestTree; import com.ruoyi.demo.domain.TestTree;
@ -33,7 +32,6 @@ public class TestTreeServiceImpl extends ServicePlusImpl<TestTreeMapper, TestTre
} }
// @DataSource(DataSourceType.SLAVE) // 切换从库查询 // @DataSource(DataSourceType.SLAVE) // 切换从库查询
@DataScope(isUser = true)
@Override @Override
public List<TestTreeVo> queryList(TestTreeBo bo) { public List<TestTreeVo> queryList(TestTreeBo bo) {
LambdaQueryWrapper<TestTree> lqw = buildQueryWrapper(bo); LambdaQueryWrapper<TestTree> lqw = buildQueryWrapper(bo);

View File

@ -1,140 +1,140 @@
package com.ruoyi.framework.aspectj; //package com.ruoyi.framework.aspectj;
//
import com.ruoyi.common.annotation.DataScope; //import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.BaseEntity; //import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysRole; //import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser; //import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser; //import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.service.UserService; //import com.ruoyi.common.core.service.UserService;
import com.ruoyi.common.utils.SecurityUtils; //import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils; //import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils; //import com.ruoyi.common.utils.spring.SpringUtils;
import org.aspectj.lang.JoinPoint; //import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect; //import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before; //import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component; //import org.springframework.stereotype.Component;
//
/** ///**
* 数据过滤处理 // * 数据过滤处理
* // *
* @author Lion Li // * @author Lion Li
*/ // */
@Aspect //@Aspect
@Component //@Component
public class DataScopeAspect { //public class DataScopeAspect {
//
/** // /**
* 全部数据权限 // * 全部数据权限
*/ // */
public static final String DATA_SCOPE_ALL = "1"; // public static final String DATA_SCOPE_ALL = "1";
//
/** // /**
* 自定数据权限 // * 自定数据权限
*/ // */
public static final String DATA_SCOPE_CUSTOM = "2"; // public static final String DATA_SCOPE_CUSTOM = "2";
//
/** // /**
* 部门数据权限 // * 部门数据权限
*/ // */
public static final String DATA_SCOPE_DEPT = "3"; // public static final String DATA_SCOPE_DEPT = "3";
//
/** // /**
* 部门及以下数据权限 // * 部门及以下数据权限
*/ // */
public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; // public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
//
/** // /**
* 仅本人数据权限 // * 仅本人数据权限
*/ // */
public static final String DATA_SCOPE_SELF = "5"; // public static final String DATA_SCOPE_SELF = "5";
//
/** // /**
* 数据权限过滤关键字 // * 数据权限过滤关键字
*/ // */
public static final String DATA_SCOPE = "dataScope"; // public static final String DATA_SCOPE = "dataScope";
//
@Before("@annotation(controllerDataScope)") // @Before("@annotation(controllerDataScope)")
public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable { // public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable {
clearDataScope(point); // clearDataScope(point);
handleDataScope(point, controllerDataScope); // handleDataScope(point, controllerDataScope);
} // }
//
protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) { // protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) {
// 获取当前的用户 // // 获取当前的用户
LoginUser loginUser = SecurityUtils.getLoginUser(); // LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNotNull(loginUser)) { // if (StringUtils.isNotNull(loginUser)) {
SysUser currentUser = SpringUtils.getBean(UserService.class).selectUserById(loginUser.getUserId()); // SysUser currentUser = SpringUtils.getBean(UserService.class).selectUserById(loginUser.getUserId());
// 如果是超级管理员则不过滤数据 // // 如果是超级管理员则不过滤数据
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) { // if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) {
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), // dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
controllerDataScope.userAlias(), controllerDataScope.isUser()); // controllerDataScope.userAlias(), controllerDataScope.isUser());
} // }
} // }
} // }
//
/** // /**
* 数据范围过滤 // * 数据范围过滤
* // *
* @param joinPoint 切点 // * @param joinPoint 切点
* @param user 用户 // * @param user 用户
* @param userAlias 别名 // * @param userAlias 别名
*/ // */
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, boolean isUser) { // public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, boolean isUser) {
StringBuilder sqlString = new StringBuilder(); // StringBuilder sqlString = new StringBuilder();
//
// "." 提取出,不写别名为单表查询,写别名为多表查询 // // "." 提取出,不写别名为单表查询,写别名为多表查询
deptAlias = StringUtils.isNotBlank(deptAlias) ? deptAlias + "." : ""; // deptAlias = StringUtils.isNotBlank(deptAlias) ? deptAlias + "." : "";
userAlias = StringUtils.isNotBlank(userAlias) ? userAlias + "." : ""; // userAlias = StringUtils.isNotBlank(userAlias) ? userAlias + "." : "";
//
for (SysRole role : user.getRoles()) { // for (SysRole role : user.getRoles()) {
String dataScope = role.getDataScope(); // String dataScope = role.getDataScope();
if (DATA_SCOPE_ALL.equals(dataScope)) { // if (DATA_SCOPE_ALL.equals(dataScope)) {
sqlString = new StringBuilder(); // sqlString = new StringBuilder();
break; // break;
} else if (DATA_SCOPE_CUSTOM.equals(dataScope)) { // } else if (DATA_SCOPE_CUSTOM.equals(dataScope)) {
sqlString.append(StringUtils.format( // sqlString.append(StringUtils.format(
" OR {}dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", // " OR {}dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ",
deptAlias, role.getRoleId())); // deptAlias, role.getRoleId()));
} else if (DATA_SCOPE_DEPT.equals(dataScope)) { // } else if (DATA_SCOPE_DEPT.equals(dataScope)) {
sqlString.append(StringUtils.format(" OR {}dept_id = {} ", // sqlString.append(StringUtils.format(" OR {}dept_id = {} ",
deptAlias, user.getDeptId())); // deptAlias, user.getDeptId()));
} else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) { // } else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
sqlString.append(StringUtils.format( // sqlString.append(StringUtils.format(
" OR {}dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", // " OR {}dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
deptAlias, user.getDeptId(), user.getDeptId())); // deptAlias, user.getDeptId(), user.getDeptId()));
} else if (DATA_SCOPE_SELF.equals(dataScope)) { // } else if (DATA_SCOPE_SELF.equals(dataScope)) {
if (isUser) { // if (isUser) {
sqlString.append(StringUtils.format(" OR {}user_id = {} ", // sqlString.append(StringUtils.format(" OR {}user_id = {} ",
userAlias, user.getUserId())); // userAlias, user.getUserId()));
} else { // } else {
// 数据权限为仅本人且没有userAlias别名不查询任何数据 // // 数据权限为仅本人且没有userAlias别名不查询任何数据
sqlString.append(" OR 1=0 "); // sqlString.append(" OR 1=0 ");
} // }
} // }
} // }
//
if (StringUtils.isNotBlank(sqlString.toString())) { // if (StringUtils.isNotBlank(sqlString.toString())) {
putDataScope(joinPoint, sqlString.substring(4)); // putDataScope(joinPoint, sqlString.substring(4));
} // }
} // }
//
/** // /**
* 拼接权限sql前先清空params.dataScope参数防止注入 // * 拼接权限sql前先清空params.dataScope参数防止注入
*/ // */
private void clearDataScope(final JoinPoint joinPoint) { // private void clearDataScope(final JoinPoint joinPoint) {
Object params = joinPoint.getArgs()[0]; // Object params = joinPoint.getArgs()[0];
if (StringUtils.isNotNull(params)) { // if (StringUtils.isNotNull(params)) {
putDataScope(joinPoint, ""); // putDataScope(joinPoint, "");
} // }
} // }
//
private static void putDataScope(JoinPoint joinPoint, String sql) { // private static void putDataScope(JoinPoint joinPoint, String sql) {
Object params = joinPoint.getArgs()[0]; // Object params = joinPoint.getArgs()[0];
if (StringUtils.isNotNull(params)) { // if (StringUtils.isNotNull(params)) {
if (params instanceof BaseEntity) { // if (params instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) params; // BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, sql); // baseEntity.getParams().put(DATA_SCOPE, sql);
} // }
} // }
} // }
} //}

View File

@ -6,10 +6,12 @@ import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.injector.ISqlInjector; import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.ruoyi.common.core.mybatisplus.methods.InsertAll; import com.ruoyi.common.core.mybatisplus.methods.InsertAll;
import com.ruoyi.framework.handler.CreateAndUpdateMetaObjectHandler; import com.ruoyi.framework.handler.CreateAndUpdateMetaObjectHandler;
import com.ruoyi.framework.handler.PlusDataPermissionHandler;
import org.mybatis.spring.annotation.MapperScan; import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -30,6 +32,8 @@ public class MybatisPlusConfig {
@Bean @Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() { public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 数据权限处理
interceptor.addInnerInterceptor(dataPermissionInterceptor());
// 分页插件 // 分页插件
interceptor.addInnerInterceptor(paginationInnerInterceptor()); interceptor.addInnerInterceptor(paginationInnerInterceptor());
// 乐观锁插件 // 乐观锁插件
@ -37,6 +41,15 @@ public class MybatisPlusConfig {
return interceptor; return interceptor;
} }
/**
* 分页插件自动识别数据库类型
*/
public DataPermissionInterceptor dataPermissionInterceptor() {
DataPermissionInterceptor dataPermissionInterceptor = new DataPermissionInterceptor();
dataPermissionInterceptor.setDataPermissionHandler(new PlusDataPermissionHandler());
return dataPermissionInterceptor;
}
/** /**
* 分页插件自动识别数据库类型 * 分页插件自动识别数据库类型
*/ */

View File

@ -0,0 +1,117 @@
package com.ruoyi.framework.handler;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.service.UserService;
import com.ruoyi.common.enums.DataScopeType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
/**
* 数据权限过滤
*
* @author Lion Li
*/
@Slf4j
public class PlusDataPermissionHandler implements DataPermissionHandler {
@Override
public Expression getSqlSegment(Expression where, String mappedStatementId) {
DataScope dataScope = findDataScopeAnnotation(mappedStatementId);
if (ObjectUtil.isNull(dataScope)) {
return where;
}
SysUser currentUser = SpringUtils.getBean(UserService.class).selectUserById(SecurityUtils.getUserId());
// 如果是超级管理员则不过滤数据
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) {
String dataScopeSql = dataScopeFilter(currentUser, dataScope);
if (StringUtils.isNotBlank(dataScopeSql)) {
try {
Expression expression = CCJSqlParserUtil.parseExpression(dataScopeSql);
return new AndExpression(where, expression);
} catch (JSQLParserException e) {
throw new ServiceException("数据权限解析异常 => " + e.getMessage());
}
}
}
return where;
}
private DataScope findDataScopeAnnotation(String mappedStatementId) {
StringBuilder sb = new StringBuilder(mappedStatementId);
int index = sb.lastIndexOf(".");
String clazzName = sb.substring(0, index);
String methodName = sb.substring(index + 1, sb.length());
Class<?> clazz = ClassUtil.loadClass(clazzName);
List<Method> methods = Arrays.stream(ClassUtil.getDeclaredMethods(clazz))
.filter(method -> method.getName().equals(methodName)).collect(Collectors.toList());
DataScope dataScope = null;
for (Method method : methods) {
if (AnnotationUtil.hasAnnotation(method, DataScope.class)) {
dataScope = AnnotationUtil.getAnnotation(method, DataScope.class);
break;
}
}
return dataScope;
}
/**
* 数据范围过滤
*
* @param user 用户
*/
public static String dataScopeFilter(SysUser user, DataScope annotation) {
StringBuilder sqlString = new StringBuilder();
ExpressionParser parser = new SpelExpressionParser();
TemplateParserContext parserContext = new TemplateParserContext();
EvaluationContext context = new StandardEvaluationContext(new HashMap<>());
context.setVariable("deptName", annotation.deptName());
context.setVariable("userName", annotation.userName());
context.setVariable("userId", user.getUserId());
context.setVariable("deptId", user.getDeptId());
for (SysRole role : user.getRoles()) {
context.setVariable("roleId", role.getRoleId());
DataScopeType type = DataScopeType.findCode(role.getDataScope());
if (ObjectUtil.isNull(type)) {
throw new ServiceException("角色数据范围异常 => " + role.getDataScope());
}
if (type == DataScopeType.DATA_SCOPE_ALL) {
break;
}
org.springframework.expression.Expression expression = parser.parseExpression(type.getSql(), parserContext);
String sql = expression.getValue(context, String.class);
sqlString.append(sql);
}
if (StringUtils.isNotBlank(sqlString.toString())) {
return sqlString.substring(4);
}
return "";
}
}

View File

@ -1,5 +1,8 @@
package com.ruoyi.system.mapper; package com.ruoyi.system.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus; import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -19,8 +22,13 @@ public interface SysDeptMapper extends BaseMapperPlus<SysDept> {
* @param dept 部门信息 * @param dept 部门信息
* @return 部门信息集合 * @return 部门信息集合
*/ */
@DataScope(deptName = "d.dept_id")
List<SysDept> selectDeptList(SysDept dept); List<SysDept> selectDeptList(SysDept dept);
@Override
@DataScope(deptName = "dept_id")
List<SysDept> selectList(@Param(Constants.WRAPPER) Wrapper<SysDept> queryWrapper);
/** /**
* 根据角色ID查询部门树信息 * 根据角色ID查询部门树信息
* *

View File

@ -1,6 +1,7 @@
package com.ruoyi.system.mapper; package com.ruoyi.system.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus; import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -14,6 +15,7 @@ import java.util.List;
*/ */
public interface SysRoleMapper extends BaseMapperPlus<SysRole> { public interface SysRoleMapper extends BaseMapperPlus<SysRole> {
@DataScope(deptName = "d.dept_id")
Page<SysRole> selectPageRoleList(@Param("page") Page<SysRole> page, @Param("role") SysRole role); Page<SysRole> selectPageRoleList(@Param("page") Page<SysRole> page, @Param("role") SysRole role);
/** /**
@ -22,6 +24,7 @@ public interface SysRoleMapper extends BaseMapperPlus<SysRole> {
* @param role 角色信息 * @param role 角色信息
* @return 角色数据集合信息 * @return 角色数据集合信息
*/ */
@DataScope(deptName = "d.dept_id")
List<SysRole> selectRoleList(SysRole role); List<SysRole> selectRoleList(SysRole role);
/** /**

View File

@ -1,6 +1,7 @@
package com.ruoyi.system.mapper; package com.ruoyi.system.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus; import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -14,6 +15,7 @@ import java.util.List;
*/ */
public interface SysUserMapper extends BaseMapperPlus<SysUser> { public interface SysUserMapper extends BaseMapperPlus<SysUser> {
@DataScope(deptName = "d.dept_id", userName = "u.user_id")
Page<SysUser> selectPageUserList(@Param("page") Page<SysUser> page, @Param("user") SysUser user); Page<SysUser> selectPageUserList(@Param("page") Page<SysUser> page, @Param("user") SysUser user);
/** /**
@ -22,6 +24,7 @@ public interface SysUserMapper extends BaseMapperPlus<SysUser> {
* @param sysUser 用户信息 * @param sysUser 用户信息
* @return 用户信息集合信息 * @return 用户信息集合信息
*/ */
@DataScope(deptName = "d.dept_id", userName = "u.user_id")
List<SysUser> selectUserList(SysUser sysUser); List<SysUser> selectUserList(SysUser sysUser);
/** /**
@ -30,6 +33,7 @@ public interface SysUserMapper extends BaseMapperPlus<SysUser> {
* @param user 用户信息 * @param user 用户信息
* @return 用户信息集合信息 * @return 用户信息集合信息
*/ */
@DataScope(deptName = "d.dept_id", userName = "u.user_id")
Page<SysUser> selectAllocatedList(@Param("page") Page<SysUser> page, @Param("user") SysUser user); Page<SysUser> selectAllocatedList(@Param("page") Page<SysUser> page, @Param("user") SysUser user);
/** /**
@ -38,6 +42,7 @@ public interface SysUserMapper extends BaseMapperPlus<SysUser> {
* @param user 用户信息 * @param user 用户信息
* @return 用户信息集合信息 * @return 用户信息集合信息
*/ */
@DataScope(deptName = "d.dept_id", userName = "u.user_id")
Page<SysUser> selectUnallocatedList(@Param("page") Page<SysUser> page, @Param("user") SysUser user); Page<SysUser> selectUnallocatedList(@Param("page") Page<SysUser> page, @Param("user") SysUser user);
/** /**

View File

@ -1,10 +1,10 @@
package com.ruoyi.system.service.impl; package com.ruoyi.system.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.tree.Tree; import cn.hutool.core.lang.tree.Tree;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysRole;
@ -46,8 +46,9 @@ public class SysDeptServiceImpl extends ServicePlusImpl<SysDeptMapper, SysDept,
* @return 部门信息集合 * @return 部门信息集合
*/ */
@Override @Override
@DataScope(deptAlias = "d")
public List<SysDept> selectDeptList(SysDept dept) { public List<SysDept> selectDeptList(SysDept dept) {
// return baseMapper.selectList();
// return baseMapper.selectList(new LambdaQueryWrapper<>());
return baseMapper.selectDeptList(dept); return baseMapper.selectDeptList(dept);
} }

View File

@ -1,5 +1,6 @@
package com.ruoyi.system.service.impl; package com.ruoyi.system.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree; import cn.hutool.core.lang.tree.Tree;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;

View File

@ -2,7 +2,6 @@ package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysRole;
@ -46,7 +45,6 @@ public class SysRoleServiceImpl extends ServicePlusImpl<SysRoleMapper, SysRole,
private SysRoleDeptMapper roleDeptMapper; private SysRoleDeptMapper roleDeptMapper;
@Override @Override
@DataScope(deptAlias = "d")
public TableDataInfo<SysRole> selectPageRoleList(SysRole role, PageQuery pageQuery) { public TableDataInfo<SysRole> selectPageRoleList(SysRole role, PageQuery pageQuery) {
Page<SysRole> page = baseMapper.selectPageRoleList(PageUtils.buildPage(pageQuery), role); Page<SysRole> page = baseMapper.selectPageRoleList(PageUtils.buildPage(pageQuery), role);
return PageUtils.buildDataInfo(page); return PageUtils.buildDataInfo(page);
@ -59,7 +57,6 @@ public class SysRoleServiceImpl extends ServicePlusImpl<SysRoleMapper, SysRole,
* @return 角色数据集合信息 * @return 角色数据集合信息
*/ */
@Override @Override
@DataScope(deptAlias = "d")
public List<SysRole> selectRoleList(SysRole role) { public List<SysRole> selectRoleList(SysRole role) {
return baseMapper.selectRoleList(role); return baseMapper.selectRoleList(role);
} }

View File

@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysRole;
@ -54,7 +53,6 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser,
private SysUserPostMapper userPostMapper; private SysUserPostMapper userPostMapper;
@Override @Override
@DataScope(deptAlias = "d", userAlias = "u", isUser = true)
public TableDataInfo<SysUser> selectPageUserList(SysUser user, PageQuery pageQuery) { public TableDataInfo<SysUser> selectPageUserList(SysUser user, PageQuery pageQuery) {
Page<SysUser> page = baseMapper.selectPageUserList(PageUtils.buildPage(pageQuery), user); Page<SysUser> page = baseMapper.selectPageUserList(PageUtils.buildPage(pageQuery), user);
return PageUtils.buildDataInfo(page); return PageUtils.buildDataInfo(page);
@ -67,7 +65,6 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser,
* @return 用户信息集合信息 * @return 用户信息集合信息
*/ */
@Override @Override
@DataScope(deptAlias = "d", userAlias = "u", isUser = true)
public List<SysUser> selectUserList(SysUser user) { public List<SysUser> selectUserList(SysUser user) {
return baseMapper.selectUserList(user); return baseMapper.selectUserList(user);
} }
@ -79,7 +76,6 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser,
* @return 用户信息集合信息 * @return 用户信息集合信息
*/ */
@Override @Override
@DataScope(deptAlias = "d", userAlias = "u", isUser = true)
public TableDataInfo<SysUser> selectAllocatedList(SysUser user, PageQuery pageQuery) { public TableDataInfo<SysUser> selectAllocatedList(SysUser user, PageQuery pageQuery) {
Page<SysUser> page = baseMapper.selectAllocatedList(PageUtils.buildPage(pageQuery), user); Page<SysUser> page = baseMapper.selectAllocatedList(PageUtils.buildPage(pageQuery), user);
return PageUtils.buildDataInfo(page); return PageUtils.buildDataInfo(page);
@ -92,7 +88,6 @@ public class SysUserServiceImpl extends ServicePlusImpl<SysUserMapper, SysUser,
* @return 用户信息集合信息 * @return 用户信息集合信息
*/ */
@Override @Override
@DataScope(deptAlias = "d", userAlias = "u", isUser = true)
public TableDataInfo<SysUser> selectUnallocatedList(SysUser user, PageQuery pageQuery) { public TableDataInfo<SysUser> selectUnallocatedList(SysUser user, PageQuery pageQuery) {
Page<SysUser> page = baseMapper.selectUnallocatedList(PageUtils.buildPage(pageQuery), user); Page<SysUser> page = baseMapper.selectUnallocatedList(PageUtils.buildPage(pageQuery), user);
return PageUtils.buildDataInfo(page); return PageUtils.buildDataInfo(page);

View File

@ -42,10 +42,10 @@
<if test="status != null and status != ''"> <if test="status != null and status != ''">
AND status = #{status} AND status = #{status}
</if> </if>
<!-- 数据范围过滤 --> <!-- &lt;!&ndash; 数据范围过滤 &ndash;&gt;-->
<if test="params.dataScope != null and params.dataScope != ''"> <!-- <if test="params.dataScope != null and params.dataScope != ''">-->
AND ( ${params.dataScope} ) <!-- AND ( ${params.dataScope} )-->
</if> <!-- </if>-->
order by d.parent_id, d.order_num order by d.parent_id, d.order_num
</select> </select>

View File

@ -60,10 +60,10 @@
<if test="role.params.endTime != null and role.params.endTime != ''"><!-- 结束时间检索 --> <if test="role.params.endTime != null and role.params.endTime != ''"><!-- 结束时间检索 -->
and date_format(r.create_time,'%y%m%d') &lt;= date_format(#{role.params.endTime},'%y%m%d') and date_format(r.create_time,'%y%m%d') &lt;= date_format(#{role.params.endTime},'%y%m%d')
</if> </if>
<!-- 数据范围过滤 --> <!-- &lt;!&ndash; 数据范围过滤 &ndash;&gt;-->
<if test="role.params.dataScope != null and role.params.dataScope != ''"> <!-- <if test="role.params.dataScope != null and role.params.dataScope != ''">-->
AND ( ${role.params.dataScope} ) <!-- AND ( ${role.params.dataScope} )-->
</if> <!-- </if>-->
order by r.role_sort order by r.role_sort
</select> </select>
@ -88,10 +88,10 @@
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 --> <if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
and date_format(r.create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d') and date_format(r.create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if> </if>
<!-- 数据范围过滤 --> <!-- &lt;!&ndash; 数据范围过滤 &ndash;&gt;-->
<if test="params.dataScope != null and params.dataScope != ''"> <!-- <if test="params.dataScope != null and params.dataScope != ''">-->
AND ( ${params.dataScope} ) <!-- AND ( ${params.dataScope} )-->
</if> <!-- </if>-->
order by r.role_sort order by r.role_sort
</select> </select>

View File

@ -108,10 +108,10 @@
AND (u.dept_id = #{user.deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{user.deptId}, AND (u.dept_id = #{user.deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{user.deptId},
ancestors) )) ancestors) ))
</if> </if>
<!-- 数据范围过滤 --> <!-- &lt;!&ndash; 数据范围过滤 &ndash;&gt;-->
<if test="user.params.dataScope != null and user.params.dataScope != ''"> <!-- <if test="user.params.dataScope != null and user.params.dataScope != ''">-->
AND ( ${user.params.dataScope} ) <!-- AND ( ${user.params.dataScope} )-->
</if> <!-- </if>-->
</select> </select>
<select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult"> <select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult">
@ -142,10 +142,10 @@
AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId},
ancestors) )) ancestors) ))
</if> </if>
<!-- 数据范围过滤 --> <!-- &lt;!&ndash; 数据范围过滤 &ndash;&gt;-->
<if test="params.dataScope != null and params.dataScope != ''"> <!-- <if test="params.dataScope != null and params.dataScope != ''">-->
AND ( ${params.dataScope} ) <!-- AND ( ${params.dataScope} )-->
</if> <!-- </if>-->
</select> </select>
<select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult"> <select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult">