1、数据权限-支持本人数据(权限控制可选:仅部门、仅本人、部门+本人)
2、数据权限-支持自动注入和手动注入(在xml中通过点位符注入) 3、数据权限-支持字段名及表别名设置
This commit is contained in:
1 parent
2cbcea03f6
commit
81a7fa8e45
6 files changed
+337
-35
No files matched your search
+156
-3
@@ -17,10 +17,12 @@
|
||||
|
||||
package com.pig4cloud.pigx.common.data.datascope;
|
||||
|
||||
import com.pig4cloud.pigx.common.data.enums.DataScopeFieldEnum;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@@ -28,22 +30,173 @@ import java.util.List;
|
||||
* @author lengleng
|
||||
* @date 2018/8/30
|
||||
* 数据权限查询参数
|
||||
*
|
||||
* update by yhaili2009@163.com at 2020/6/17
|
||||
* 1、支持本人数据权限过滤;
|
||||
* 2、支持自动注入、手动注入;
|
||||
* 3、支持字段名称及表别名设置;
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DataScope extends HashMap {
|
||||
/**
|
||||
* 限制范围的字段名称
|
||||
* sql中的占位符,需要xml中和此处一致,会被替换为真正的数据权限语句
|
||||
* add by yhaili2009@163.com at 2020/6/17
|
||||
*/
|
||||
private String sqlPlaceholder = "[scope.scopeSql]";
|
||||
/**
|
||||
* 用户ID的引用别名(autoInj为false时会用到)
|
||||
* add by yhaili2009@163.com at 2020/6/17
|
||||
*/
|
||||
private String userAlias;
|
||||
/**
|
||||
* 部门ID的引用别名(autoInj为false时会用到)
|
||||
* add by yhaili2009@163.com at 2020/6/17
|
||||
*/
|
||||
private String deptAlias;
|
||||
/**
|
||||
* 数据权限 sql语句,用于在自定义sql中引入
|
||||
* add by yhaili2009@163.com at 2020/6/17
|
||||
*/
|
||||
private String scopeSql = "";
|
||||
/**
|
||||
* 是否自动注入数据权限的sql, 为false时,需要自己在sql中通过 scopeSql 引入
|
||||
* add by yhaili2009@163.com at 2020/6/17
|
||||
*/
|
||||
private boolean autoInj = true;
|
||||
/**
|
||||
* 限制范围的字段名称(用户)
|
||||
* add by yhaili2009@163.com at 2020/6/17
|
||||
*/
|
||||
private String userScopeName = "user_id";
|
||||
/**
|
||||
* 限制范围的字段名称(部门)
|
||||
*/
|
||||
private String scopeName = "dept_id";
|
||||
|
||||
/**
|
||||
* 具体的数据范围
|
||||
* 具体的数据范围(部门)
|
||||
*/
|
||||
private List<Integer> deptIds = new ArrayList<>();
|
||||
private List<Integer> scopeIds = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 是否只查询本部门
|
||||
*/
|
||||
private Boolean isOnly = false;
|
||||
|
||||
/**
|
||||
* 数据权限字段
|
||||
* add by yhaili2009@163.com at 2020/6/17
|
||||
*/
|
||||
private DataScopeFieldEnum scopeField;
|
||||
|
||||
public DataScope() {
|
||||
this(DataScopeFieldEnum.DEPT);
|
||||
}
|
||||
|
||||
public DataScope(DataScopeFieldEnum scopeField) {
|
||||
this.scopeField = scopeField;
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅控制用户数据权限
|
||||
* @return
|
||||
*/
|
||||
public static DataScope onlyUser() {
|
||||
return new DataScope(DataScopeFieldEnum.USER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅控制部门数据权限
|
||||
* @return
|
||||
*/
|
||||
public static DataScope onlyDept() {
|
||||
return new DataScope(DataScopeFieldEnum.DEPT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 可控制部门和用户数据权限
|
||||
* @return
|
||||
*/
|
||||
public static DataScope deptAndUser() {
|
||||
return new DataScope(DataScopeFieldEnum.DEPT_AND_USER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否开启自动注入权限sql
|
||||
* @param autoInj
|
||||
* @return
|
||||
*/
|
||||
public DataScope autoInj(boolean autoInj) {
|
||||
this.autoInj = autoInj;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置部门ID引用的别名
|
||||
* @param deptAlias
|
||||
* @return
|
||||
*/
|
||||
public DataScope deptAlias(String deptAlias) {
|
||||
this.deptAlias = deptAlias;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户ID引用的别名
|
||||
* @param userAlias
|
||||
* @return
|
||||
*/
|
||||
public DataScope userAlias(String userAlias) {
|
||||
this.userAlias = userAlias;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置部门字段名
|
||||
* @param deptScopeName
|
||||
* @return
|
||||
*/
|
||||
public DataScope deptScopeName(String deptScopeName) {
|
||||
this.scopeName = deptScopeName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户字段名
|
||||
* @param userScopeName
|
||||
* @return
|
||||
*/
|
||||
public DataScope userScopeName(String userScopeName) {
|
||||
this.userScopeName = userScopeName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置数据权限 sql占位符
|
||||
* @param sqlPlaceholder
|
||||
* @return
|
||||
*/
|
||||
public DataScope sqlPlaceholder(String sqlPlaceholder) {
|
||||
this.sqlPlaceholder = sqlPlaceholder;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义可以查看的部门ID
|
||||
* @param deptId
|
||||
* @return
|
||||
*/
|
||||
public DataScope scopeIds(Integer ...deptId) {
|
||||
this.scopeIds.addAll(Arrays.asList(deptId));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限sql不能在其他地方修改
|
||||
* @param scopeSql
|
||||
*/
|
||||
protected void setScopeSql(String scopeSql) {
|
||||
this.scopeSql = scopeSql;
|
||||
}
|
||||
}
|
||||
+5
-4
@@ -17,8 +17,6 @@
|
||||
|
||||
package com.pig4cloud.pigx.common.data.datascope;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2019-09-07
|
||||
@@ -30,8 +28,11 @@ public interface DataScopeHandle {
|
||||
/**
|
||||
* 计算用户数据权限
|
||||
*
|
||||
* @param deptList
|
||||
* @param dataScope
|
||||
* @return
|
||||
*
|
||||
* update by yhaili2009@163.com at 2020/6/17
|
||||
* 修改参数 List<Integer> 为 DataScope
|
||||
*/
|
||||
Boolean calcScope(List<Integer> deptList);
|
||||
Boolean calcScope(DataScope dataScope);
|
||||
}
|
||||
+36
-13
@@ -17,7 +17,6 @@
|
||||
|
||||
package com.pig4cloud.pigx.common.data.datascope;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
|
||||
import com.baomidou.mybatisplus.extension.handlers.AbstractSqlParserHandler;
|
||||
@@ -43,6 +42,11 @@ import java.util.Properties;
|
||||
* @date 2018/12/26
|
||||
* <p>
|
||||
* mybatis 数据权限拦截器
|
||||
*
|
||||
* update by yhaili2009@163.com at 2020/6/17
|
||||
* 1、支持本人数据权限过滤;
|
||||
* 2、支持自动注入、手动注入;
|
||||
* 3、支持字段名称及表别名设置;
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
@@ -56,11 +60,6 @@ public class DataScopeInterceptor extends AbstractSqlParserHandler implements In
|
||||
StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget());
|
||||
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
|
||||
this.sqlParser(metaObject);
|
||||
// 先判断是不是SELECT操作
|
||||
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
|
||||
if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
|
||||
String originalSql = boundSql.getSql();
|
||||
@@ -72,14 +71,38 @@ public class DataScopeInterceptor extends AbstractSqlParserHandler implements In
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
String scopeName = dataScope.getScopeName();
|
||||
List<Integer> deptIds = dataScope.getDeptIds();
|
||||
// 优先获取赋值数据
|
||||
if (CollUtil.isEmpty(deptIds) && dataScopeHandle.calcScope(deptIds)) {
|
||||
return invocation.proceed();
|
||||
/**
|
||||
* 这里分自动注入和手动注入处理; 自动注入维持原来的逻辑不变
|
||||
* update by yhaili2009@163.com at 2020/6/17
|
||||
*/
|
||||
if (dataScope.isAutoInj()) {
|
||||
// 先判断是不是SELECT操作
|
||||
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
|
||||
if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
// 优先获取赋值数据
|
||||
if (dataScopeHandle.calcScope(dataScope)) {
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
String scopeName = dataScope.getScopeName();
|
||||
List<Integer> scopeIds = dataScope.getScopeIds();
|
||||
|
||||
String join = CollectionUtil.join(scopeIds, ",");
|
||||
originalSql = "select * from (" + originalSql + ") temp_data_scope where temp_data_scope." + scopeName + " in (" + join + ")";
|
||||
}
|
||||
String join = CollectionUtil.join(deptIds, ",");
|
||||
originalSql = "select * from (" + originalSql + ") temp_data_scope where temp_data_scope." + scopeName + " in (" + join + ")";
|
||||
/**
|
||||
* 手动插入sql中(通过字符串占位)
|
||||
* add by yhaili2009@163.com at 2020/6/17
|
||||
*/
|
||||
else {
|
||||
dataScopeHandle.calcScope(dataScope);
|
||||
|
||||
originalSql = originalSql.replace(dataScope.getSqlPlaceholder(), dataScope.getScopeSql() + " ");
|
||||
}
|
||||
|
||||
metaObject.setValue("delegate.boundSql.sql", originalSql);
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
+75
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
* Copyright (c) 2018-2025, ihealth All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@@ -12,46 +12,75 @@
|
||||
* 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)
|
||||
* Author: ihealth
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.common.data.datascope;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.pig4cloud.pigx.admin.api.entity.SysDeptRelation;
|
||||
import com.pig4cloud.pigx.admin.api.entity.SysRole;
|
||||
import com.pig4cloud.pigx.admin.api.feign.RemoteDataScopeService;
|
||||
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
|
||||
import com.pig4cloud.pigx.common.data.enums.DataScopeFieldEnum;
|
||||
import com.pig4cloud.pigx.common.data.enums.DataScopeTypeEnum;
|
||||
import com.pig4cloud.pigx.common.security.service.PigxUser;
|
||||
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @author ihealth
|
||||
* @date 2019-09-07
|
||||
* <p>
|
||||
* 默认data scope 判断处理器
|
||||
*
|
||||
* update by yhaili2009@163.com at 2020/6/17
|
||||
* 1、支持本人数据权限过滤;
|
||||
* 2、支持自动注入、手动注入;
|
||||
* 3、支持字段名称及表别名设置;
|
||||
*/
|
||||
public class PigxDefaultDatascopeHandle implements DataScopeHandle {
|
||||
|
||||
@Autowired
|
||||
private RemoteDataScopeService dataScopeService;
|
||||
|
||||
/**
|
||||
* 计算用户数据权限
|
||||
*
|
||||
* @param deptList
|
||||
* @param dataScope
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Boolean calcScope(List<Integer> deptList) {
|
||||
public Boolean calcScope(DataScope dataScope) {
|
||||
// 默认数据权限sql为空,即不限制
|
||||
dataScope.setScopeSql("");
|
||||
|
||||
// 优先获取赋值数据
|
||||
if (CollUtil.isNotEmpty(dataScope.getScopeIds())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Integer> scopeList = dataScope.getScopeIds();
|
||||
if (scopeList == null) {
|
||||
scopeList = new ArrayList<>();
|
||||
}
|
||||
// 默认为部门数据权限控制
|
||||
// dataScope.setScopeName(DEPT_SCOPE_NAME);
|
||||
|
||||
PigxUser user = SecurityUtils.getUser();
|
||||
// 当前用户为空(一般后台处理程序),给所有数据
|
||||
if (user == null) {
|
||||
return true;
|
||||
}
|
||||
List<String> roleIdList = user.getAuthorities()
|
||||
.stream().map(GrantedAuthority::getAuthority)
|
||||
.filter(authority -> authority.startsWith(SecurityConstants.ROLE))
|
||||
@@ -62,27 +91,62 @@ public class PigxDefaultDatascopeHandle implements DataScopeHandle {
|
||||
.min(Comparator.comparingInt(SysRole::getDsType)).get();
|
||||
|
||||
Integer dsType = role.getDsType();
|
||||
// 仅支持用户字段的数据权限时,角色指定不是仅本人数据
|
||||
if (dataScope.getScopeField() == DataScopeFieldEnum.USER && dsType != DataScopeTypeEnum.OWN.getType()) {
|
||||
return true;
|
||||
}
|
||||
// 仅支持部门字段数据权限时,角色指定只能查看仅本人数据
|
||||
if (dataScope.getScopeField() == DataScopeFieldEnum.DEPT && dsType == DataScopeTypeEnum.OWN.getType()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 默认为部门数据权限过滤
|
||||
String alias = dataScope.getDeptAlias();
|
||||
|
||||
// 查询全部
|
||||
if (DataScopeTypeEnum.ALL.getType() == dsType) {
|
||||
return true;
|
||||
}
|
||||
// 自定义
|
||||
if (DataScopeTypeEnum.CUSTOM.getType() == dsType) {
|
||||
else if (DataScopeTypeEnum.CUSTOM.getType() == dsType) {
|
||||
String dsScope = role.getDsScope();
|
||||
deptList.addAll(Arrays.stream(dsScope.split(StrUtil.COMMA))
|
||||
scopeList.addAll(Arrays.stream(dsScope.split(StrUtil.COMMA))
|
||||
.map(Integer::parseInt).collect(Collectors.toList()));
|
||||
}
|
||||
// 查询本级及其下级
|
||||
if (DataScopeTypeEnum.OWN_CHILD_LEVEL.getType() == dsType) {
|
||||
else if (DataScopeTypeEnum.OWN_CHILD_LEVEL.getType() == dsType) {
|
||||
List<Integer> deptIdList = dataScopeService.getDescendantList(user.getDeptId())
|
||||
.getData().stream().map(SysDeptRelation::getDescendant)
|
||||
.collect(Collectors.toList());
|
||||
deptList.addAll(deptIdList);
|
||||
scopeList.addAll(deptIdList);
|
||||
}
|
||||
// 只查询本级
|
||||
if (DataScopeTypeEnum.OWN_LEVEL.getType() == dsType) {
|
||||
deptList.add(user.getDeptId());
|
||||
else if (DataScopeTypeEnum.OWN_LEVEL.getType() == dsType) {
|
||||
scopeList.add(user.getDeptId());
|
||||
}
|
||||
/**
|
||||
* 只查询本人
|
||||
* add by yhaili2009@163.com at 2020/6/17
|
||||
*/
|
||||
else if (DataScopeTypeEnum.OWN.getType() == dsType) {
|
||||
scopeList.add(user.getId());
|
||||
// 设置用户数据权限控制
|
||||
dataScope.setScopeName(dataScope.getUserScopeName());
|
||||
alias = dataScope.getUserAlias();
|
||||
}
|
||||
|
||||
alias = StrUtil.isBlank(alias) ? "" : alias + ".";
|
||||
if (scopeList.isEmpty()) {
|
||||
// 没有任何权限,不返回任何数据
|
||||
dataScope.setScopeSql(" AND 1=0");
|
||||
} else if (scopeList.size() == 1) {
|
||||
dataScope.setScopeSql(" AND " + alias + dataScope.getScopeName() + " = " + scopeList.get(0));
|
||||
} else {
|
||||
String join = CollectionUtil.join(scopeList, ",");
|
||||
dataScope.setScopeSql(" AND " + alias + dataScope.getScopeName() + " IN (" + join + ")");
|
||||
}
|
||||
|
||||
dataScope.setScopeIds(scopeList);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.pig4cloud.pigx.common.data.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 数据权限支持的模式
|
||||
* @author yhaili2009@163.com
|
||||
* @date 2020/6/17
|
||||
*
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum DataScopeFieldEnum {
|
||||
/**
|
||||
* 仅支持部门
|
||||
*/
|
||||
DEPT(0, "仅部门"),
|
||||
|
||||
/**
|
||||
* 仅支持用户
|
||||
*/
|
||||
USER(1, "仅用户"),
|
||||
|
||||
/**
|
||||
* 支持部门和用户
|
||||
*/
|
||||
DEPT_AND_USER(2, "部门和用户");
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final int type;
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String description;
|
||||
}
|
||||
+10
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, lengleng All rights reserved.
|
||||
* Copyright (c) 2018-2025, ihealth All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
@@ -12,7 +12,7 @@
|
||||
* 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)
|
||||
* Author: ihealth
|
||||
*/
|
||||
|
||||
package com.pig4cloud.pigx.common.data.enums;
|
||||
@@ -21,7 +21,7 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @author ihealth
|
||||
* @date 2018/12/26
|
||||
* <p>
|
||||
* 数据权限类型
|
||||
@@ -47,7 +47,13 @@ public enum DataScopeTypeEnum {
|
||||
/**
|
||||
* 本级
|
||||
*/
|
||||
OWN_LEVEL(3, "本级");
|
||||
OWN_LEVEL(3, "本级"),
|
||||
|
||||
/**
|
||||
* 本人
|
||||
* add by yhaili2009@163.com at 2020/6/17
|
||||
*/
|
||||
OWN(4, "本人");
|
||||
|
||||
/**
|
||||
* 类型
|
||||
|
||||
Reference in new issue
Block a user