🤡 增强数据权限 支持跨服务问题

This commit is contained in:
冷冷 committed 2019-09-07 20:18:19 +08:00
1 parent e0b2776c68
commit 03ae63a2b9
7 files changed
+233 -50

No files matched your search

@@ -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);
}
@@ -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();
}
/**
* 生成拦截对象的代理
*
@@ -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;
}
}
@@ -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());
}
/**
@@ -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);
}
@@ -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)));
}
}
@@ -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));
}
}