mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-08 12:39:05 +08:00
🤡 增强数据权限 支持跨服务问题
This commit is contained in:
1 parent
e0b2776c68
commit
03ae63a2b9
7 files changed
+233
-50
No files matched your search
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.datascope;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2019-09-07
|
||||
* <p>
|
||||
* data scope 判断处理器,抽象服务扩展
|
||||
*/
|
||||
public interface DataScopeHandle {
|
||||
|
||||
/**
|
||||
* 计算用户数据权限
|
||||
*
|
||||
* @param deptList
|
||||
* @return
|
||||
*/
|
||||
Boolean calcScope(List<Integer> deptList);
|
||||
}
|
||||
+7
-47
@@ -19,15 +19,8 @@ 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 cn.hutool.db.Db;
|
||||
import cn.hutool.db.Entity;
|
||||
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
|
||||
import com.baomidou.mybatisplus.extension.handlers.AbstractSqlParserHandler;
|
||||
import com.pig4cloud.pigx.common.core.constant.SecurityConstants;
|
||||
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 lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -38,12 +31,11 @@ import org.apache.ibatis.mapping.SqlCommandType;
|
||||
import org.apache.ibatis.plugin.*;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.apache.ibatis.reflection.SystemMetaObject;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
/**
|
||||
@@ -56,7 +48,7 @@ import java.util.stream.Collectors;
|
||||
@AllArgsConstructor
|
||||
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
|
||||
public class DataScopeInterceptor extends AbstractSqlParserHandler implements Interceptor {
|
||||
private final DataSource dataSource;
|
||||
private final DataScopeHandle dataScopeHandle;
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
@@ -83,41 +75,8 @@ public class DataScopeInterceptor extends AbstractSqlParserHandler implements In
|
||||
String scopeName = dataScope.getScopeName();
|
||||
List<Integer> deptIds = dataScope.getDeptIds();
|
||||
// 优先获取赋值数据
|
||||
if (CollUtil.isEmpty(deptIds)) {
|
||||
PigxUser user = SecurityUtils.getUser();
|
||||
List<String> roleIdList = user.getAuthorities()
|
||||
.stream().map(GrantedAuthority::getAuthority)
|
||||
.filter(authority -> authority.startsWith(SecurityConstants.ROLE))
|
||||
.map(authority -> authority.split(StrUtil.UNDERLINE)[1])
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Entity query = Db.use(dataSource)
|
||||
.query("SELECT * FROM sys_role where role_id IN (" + CollUtil.join(roleIdList, ",") + ")")
|
||||
.stream().min(Comparator.comparingInt(o -> o.getInt("ds_type"))).get();
|
||||
|
||||
Integer dsType = query.getInt("ds_type");
|
||||
// 查询全部
|
||||
if (DataScopeTypeEnum.ALL.getType() == dsType) {
|
||||
return invocation.proceed();
|
||||
}
|
||||
// 自定义
|
||||
if (DataScopeTypeEnum.CUSTOM.getType() == dsType) {
|
||||
String dsScope = query.getStr("ds_scope");
|
||||
deptIds.addAll(Arrays.stream(dsScope.split(StrUtil.COMMA))
|
||||
.map(Integer::parseInt).collect(Collectors.toList()));
|
||||
}
|
||||
// 查询本级及其下级
|
||||
if (DataScopeTypeEnum.OWN_CHILD_LEVEL.getType() == dsType) {
|
||||
List<Integer> deptIdList = Db.use(dataSource)
|
||||
.findBy("sys_dept_relation", "ancestor", user.getDeptId())
|
||||
.stream().map(entity -> entity.getInt("descendant"))
|
||||
.collect(Collectors.toList());
|
||||
deptIds.addAll(deptIdList);
|
||||
}
|
||||
// 只查询本级
|
||||
if (DataScopeTypeEnum.OWN_LEVEL.getType() == dsType) {
|
||||
deptIds.add(user.getDeptId());
|
||||
}
|
||||
if (CollUtil.isEmpty(deptIds) && dataScopeHandle.calcScope(deptIds)) {
|
||||
return invocation.proceed();
|
||||
}
|
||||
String join = CollectionUtil.join(deptIds, ",");
|
||||
originalSql = "select * from (" + originalSql + ") temp_data_scope where temp_data_scope." + scopeName + " in (" + join + ")";
|
||||
@@ -125,6 +84,7 @@ public class DataScopeInterceptor extends AbstractSqlParserHandler implements In
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成拦截对象的代理
|
||||
*
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.datascope;
|
||||
|
||||
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.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.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2019-09-07
|
||||
* <p>
|
||||
* 默认data scope 判断处理器
|
||||
*/
|
||||
public class PigxDefaultDatascopeHandle implements DataScopeHandle {
|
||||
@Autowired
|
||||
private RemoteDataScopeService dataScopeService;
|
||||
|
||||
/**
|
||||
* 计算用户数据权限
|
||||
*
|
||||
* @param deptList
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Boolean calcScope(List<Integer> deptList) {
|
||||
PigxUser user = SecurityUtils.getUser();
|
||||
List<String> roleIdList = user.getAuthorities()
|
||||
.stream().map(GrantedAuthority::getAuthority)
|
||||
.filter(authority -> authority.startsWith(SecurityConstants.ROLE))
|
||||
.map(authority -> authority.split(StrUtil.UNDERLINE)[1])
|
||||
.collect(Collectors.toList());
|
||||
|
||||
SysRole role = dataScopeService.getRoleList(roleIdList).getData().stream()
|
||||
.min(Comparator.comparingInt(SysRole::getDsType)).get();
|
||||
|
||||
Integer dsType = role.getDsType();
|
||||
// 查询全部
|
||||
if (DataScopeTypeEnum.ALL.getType() == dsType) {
|
||||
return true;
|
||||
}
|
||||
// 自定义
|
||||
if (DataScopeTypeEnum.CUSTOM.getType() == dsType) {
|
||||
String dsScope = role.getDsScope();
|
||||
deptList.addAll(Arrays.stream(dsScope.split(StrUtil.COMMA))
|
||||
.map(Integer::parseInt).collect(Collectors.toList()));
|
||||
}
|
||||
// 查询本级及其下级
|
||||
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);
|
||||
}
|
||||
// 只查询本级
|
||||
if (DataScopeTypeEnum.OWN_LEVEL.getType() == dsType) {
|
||||
deptList.add(user.getDeptId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+15
-3
@@ -22,7 +22,9 @@ import com.baomidou.mybatisplus.core.parser.ISqlParser;
|
||||
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
|
||||
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
|
||||
import com.pig4cloud.pigx.common.data.datascope.DataScopeHandle;
|
||||
import com.pig4cloud.pigx.common.data.datascope.DataScopeInterceptor;
|
||||
import com.pig4cloud.pigx.common.data.datascope.PigxDefaultDatascopeHandle;
|
||||
import com.pig4cloud.pigx.common.data.tenant.PigxTenantHandler;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
@@ -77,16 +79,26 @@ public class MybatisPlusConfig {
|
||||
return paginationInterceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* pigx 默认数据权限处理
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DataScopeHandle dataScopeHandle() {
|
||||
return new PigxDefaultDatascopeHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据权限插件
|
||||
*
|
||||
* @param dataSource 数据源
|
||||
* @return DataScopeInterceptor
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DataScopeInterceptor dataScopeInterceptor(DataSource dataSource) {
|
||||
return new DataScopeInterceptor(dataSource);
|
||||
public DataScopeInterceptor dataScopeInterceptor() {
|
||||
return new DataScopeInterceptor(dataScopeHandle());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.admin.api.feign;
|
||||
|
||||
import com.pig4cloud.pigx.admin.api.entity.SysDeptRelation;
|
||||
import com.pig4cloud.pigx.admin.api.entity.SysRole;
|
||||
import com.pig4cloud.pigx.common.core.constant.ServiceNameConstants;
|
||||
import com.pig4cloud.pigx.common.core.util.R;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
* @date 2019-09-07
|
||||
* <p>
|
||||
* 远程数据权限调用接口
|
||||
*/
|
||||
@FeignClient(contextId = "remoteDataScopeService", value = ServiceNameConstants.UPMS_SERVICE)
|
||||
public interface RemoteDataScopeService {
|
||||
|
||||
/**
|
||||
* 通过角色ID 查询角色列表
|
||||
*
|
||||
* @param roleIdList 角色ID
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/role/getRoleList")
|
||||
R<List<SysRole>> getRoleList(@RequestBody List<String> roleIdList);
|
||||
|
||||
/**
|
||||
* 获取子级部门
|
||||
*
|
||||
* @param deptId 部门ID
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/dept/getDescendantList/{deptId}")
|
||||
R<List<SysDeptRelation>> getDescendantList(@PathVariable("deptId") Integer deptId);
|
||||
}
|
||||
+16
@@ -19,7 +19,10 @@
|
||||
|
||||
package com.pig4cloud.pigx.admin.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.pig4cloud.pigx.admin.api.entity.SysDept;
|
||||
import com.pig4cloud.pigx.admin.api.entity.SysDeptRelation;
|
||||
import com.pig4cloud.pigx.admin.service.SysDeptRelationService;
|
||||
import com.pig4cloud.pigx.admin.service.SysDeptService;
|
||||
import com.pig4cloud.pigx.common.core.util.R;
|
||||
import com.pig4cloud.pigx.common.log.annotation.SysLog;
|
||||
@@ -44,6 +47,7 @@ import java.time.LocalDateTime;
|
||||
@RequestMapping("/dept")
|
||||
@Api(value = "dept", tags = "部门管理模块")
|
||||
public class SysDeptController {
|
||||
private final SysDeptRelationService relationService;
|
||||
private final SysDeptService sysDeptService;
|
||||
|
||||
/**
|
||||
@@ -107,4 +111,16 @@ public class SysDeptController {
|
||||
sysDept.setUpdateTime(LocalDateTime.now());
|
||||
return R.ok(sysDeptService.updateDeptById(sysDept));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查收子级列表
|
||||
*
|
||||
* @return 返回子级
|
||||
*/
|
||||
@GetMapping(value = "/getDescendantList/{deptId}")
|
||||
public R getDescendantList(@PathVariable Integer deptId) {
|
||||
return R.ok(relationService.list(Wrappers.<SysDeptRelation>lambdaQuery()
|
||||
.eq(SysDeptRelation::getAncestor, deptId)));
|
||||
}
|
||||
|
||||
}
|
||||
+12
@@ -32,6 +32,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author lengleng
|
||||
@@ -130,4 +131,15 @@ public class SysRoleController {
|
||||
SysRole sysRole = sysRoleService.getById(roleId);
|
||||
return R.ok(sysRoleMenuService.saveRoleMenus(sysRole.getRoleCode(), roleId, menuIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过角色ID 查询角色列表
|
||||
*
|
||||
* @param roleIdList 角色ID
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/getRoleList")
|
||||
public R getRoleList(@RequestBody List<String> roleIdList) {
|
||||
return R.ok(sysRoleService.listByIds(roleIdList));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user