|
@@ -1,288 +0,0 @@
|
|
|
-package com.zd.security.config;
|
|
|
|
|
-
|
|
|
|
|
-import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
|
|
|
|
|
-import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
|
|
|
|
|
-import com.zd.common.core.security.TokenService;
|
|
|
|
|
-import com.zd.common.core.utils.DateUtils;
|
|
|
|
|
-import com.zd.common.core.utils.ServletUtils;
|
|
|
|
|
-import com.zd.common.core.utils.SpringUtils;
|
|
|
|
|
-import com.zd.common.core.utils.StringUtils;
|
|
|
|
|
-import com.zd.model.entity.*;
|
|
|
|
|
-import com.zd.model.enums.DataPermissionEnum;
|
|
|
|
|
-import com.zd.security.scope.DataPermission;
|
|
|
|
|
-import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
-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 javax.servlet.http.HttpSession;
|
|
|
|
|
-import java.lang.reflect.Method;
|
|
|
|
|
-import java.util.*;
|
|
|
|
|
-import java.util.stream.Collectors;
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * <p>数据权限</p>
|
|
|
|
|
- *
|
|
|
|
|
- * @author: linft
|
|
|
|
|
- * @date: 2023/4/19
|
|
|
|
|
- * @since:
|
|
|
|
|
- */
|
|
|
|
|
-@Slf4j
|
|
|
|
|
-public class DataScopeInterceptor implements InnerInterceptor {
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds,
|
|
|
|
|
- ResultHandler resultHandler, BoundSql boundSql) {
|
|
|
|
|
- long startTime = System.currentTimeMillis();
|
|
|
|
|
- log.info("beforeQuery starting.........,startTime :{}",startTime);
|
|
|
|
|
- PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
|
|
|
|
|
- String originalSql = boundSql.getSql();
|
|
|
|
|
-
|
|
|
|
|
- LoginModel loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
|
|
|
|
|
- if (loginUser != null) {
|
|
|
|
|
- HttpSession session = ServletUtils.getRequest().getSession();
|
|
|
|
|
- String key = null;
|
|
|
|
|
- DataPermission dataScope = getDataPermission(ms);
|
|
|
|
|
- if (dataScope == null) {
|
|
|
|
|
- long strap = DateUtils.getCurrentTimeMillisRound() - 200;
|
|
|
|
|
- Map<String,DataPermission> map = getDataPermissionBySession(strap,loginUser,session);
|
|
|
|
|
- Set<String> set = map.keySet();
|
|
|
|
|
- if (set != null && !set.isEmpty()) {
|
|
|
|
|
- List<String> list = new ArrayList(set);
|
|
|
|
|
- key = list.get(0);
|
|
|
|
|
- dataScope = map.get(key);
|
|
|
|
|
- }
|
|
|
|
|
- dataScope = (DataPermission) session.getAttribute(key);
|
|
|
|
|
- log.info("【数据权限】注解接收获取注解信息:key = {}, dataScope = {}", key, dataScope);
|
|
|
|
|
- }
|
|
|
|
|
- if (dataScope == null) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- //检查排除的角色项
|
|
|
|
|
- String[] arr = dataScope.exclusions();
|
|
|
|
|
- List<LoginRole> useRoles = null;
|
|
|
|
|
- if (arr != null && arr.length > 0) {
|
|
|
|
|
- List<String> list = Arrays.asList(arr);
|
|
|
|
|
- useRoles = loginUser.getRoles().stream().filter(r -> !list.contains(r.getRoleKey())).collect(Collectors.toList());
|
|
|
|
|
- } else {
|
|
|
|
|
- useRoles = loginUser.getRoles();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- Long roleId = null;
|
|
|
|
|
- Integer scope = DataPermissionEnum.DATA_SCOPE_ALL.getType();
|
|
|
|
|
- //检查指定的角色项
|
|
|
|
|
- String roleKey = dataScope.roleKey();
|
|
|
|
|
- if (useRoles != null && !useRoles.isEmpty()) {
|
|
|
|
|
- if (!"".equals(roleKey)) {
|
|
|
|
|
- List<LoginRole> roles = useRoles.stream().filter(r -> roleKey.equals(r.getRoleKey())).collect(Collectors.toList());
|
|
|
|
|
- if (roles != null && !roles.isEmpty()) {
|
|
|
|
|
- roleId = roles.get(0).getRoleId();
|
|
|
|
|
- scope = roles.get(0).getDataScope();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- if (roleId == null) {
|
|
|
|
|
- List<LoginRole> roles = useRoles.stream().sorted(Comparator.comparing(LoginRole::getDataScope)).collect(Collectors.toList());
|
|
|
|
|
- roleId = roles.get(0).getRoleId();
|
|
|
|
|
- scope = roles.get(0).getDataScope();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- // 如果是超级管理员,则不过滤数据
|
|
|
|
|
- if (!loginUser.isAdmin()) {
|
|
|
|
|
- if (scope == null || DataPermissionEnum.DATA_SCOPE_ALL.getType() == scope) {
|
|
|
|
|
- log.info("【数据权限】 所有权限或未分配,不处理");
|
|
|
|
|
- } else if (DataPermissionEnum.DATA_SCOPE_DEPT.getType() == scope) {
|
|
|
|
|
- log.info("【数据权限】 部门权限,查本部门数据");
|
|
|
|
|
- SysDeptUser deptUser = getDeptUser(session, loginUser);
|
|
|
|
|
- List<Long> userIds = getPermissionUserIds(deptUser,Boolean.FALSE);
|
|
|
|
|
- originalSql = sqlHandle(originalSql, dataScope, loginUser, Boolean.TRUE, userIds);
|
|
|
|
|
- } else if (DataPermissionEnum.DATA_SCOPE_DEPT_AND_CHILD.getType() == scope) {
|
|
|
|
|
- log.info("【数据权限】 部门及子部门权限,查本部门及下属部门数据");
|
|
|
|
|
- SysDeptUser deptUser = getDeptUser(session, loginUser);
|
|
|
|
|
- List<Long> userIds = getPermissionUserIds(deptUser,Boolean.TRUE);
|
|
|
|
|
- originalSql = sqlHandle(originalSql, dataScope, loginUser, Boolean.TRUE, userIds);
|
|
|
|
|
- } else if (DataPermissionEnum.DATA_SCOPE_SELF.getType() == scope) {
|
|
|
|
|
- log.info("【数据权限】 个人权限,只可查个人创建的数据");
|
|
|
|
|
- originalSql = sqlHandle(originalSql, dataScope, loginUser, Boolean.FALSE, null);
|
|
|
|
|
- } else if (DataPermissionEnum.DATA_SCOPE_CUSTOM.getType() == scope) {
|
|
|
|
|
- log.info("【数据权限】 自定义,查自定义指定的部分数据");
|
|
|
|
|
- List<Long> userIds = getCustomRoleUserIds(session, loginUser.getToken(), roleId);
|
|
|
|
|
- originalSql = sqlHandle(originalSql, dataScope, loginUser, Boolean.TRUE, userIds);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- session.removeAttribute(key);
|
|
|
|
|
- }
|
|
|
|
|
- mpBs.sql(originalSql);
|
|
|
|
|
- long endTime = System.currentTimeMillis();
|
|
|
|
|
- long executionTime = (endTime - startTime) / 1000;
|
|
|
|
|
- log.info("beforeQuery end,endTime:{},takes about {} seconds",endTime,executionTime);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private DataPermission getDataPermission(MappedStatement ms) {
|
|
|
|
|
- DataPermission dataAuth = null;
|
|
|
|
|
- String id = ms.getId();
|
|
|
|
|
- try {
|
|
|
|
|
- String className = id.substring(0, id.lastIndexOf("."));
|
|
|
|
|
- String methodName = id.substring(id.lastIndexOf(".") + 1);
|
|
|
|
|
- final Class<?> cls = Class.forName(className);
|
|
|
|
|
- final Method[] methods = cls.getMethods();
|
|
|
|
|
- for (Method method : methods) {
|
|
|
|
|
- if (method.getName().equals(methodName) && method.isAnnotationPresent(DataPermission.class)) {
|
|
|
|
|
- dataAuth = method.getAnnotation(DataPermission.class);
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return dataAuth;
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.info("【数据权限】 获取权限注解异常,异常信息:",e);
|
|
|
|
|
- }
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 拼装本部门/本部门及以下 对应用户id
|
|
|
|
|
- * @param deptUser
|
|
|
|
|
- * @param needChildDept
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- private List<Long> getPermissionUserIds(SysDeptUser deptUser, Boolean needChildDept) {
|
|
|
|
|
- List<Long> userIds = deptUser.getDeptUserIds();
|
|
|
|
|
- if (needChildDept != null && needChildDept) {
|
|
|
|
|
- SysDeptUser childUsers = deptUser.getChildDeptUser();
|
|
|
|
|
- if (childUsers != null) {
|
|
|
|
|
- userIds.addAll(childUsers.getDeptUserIds());
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return userIds;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * sql处理
|
|
|
|
|
- * @param originalSql
|
|
|
|
|
- * @param dataScope
|
|
|
|
|
- * @param userIds
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- private String sqlHandle(String originalSql, DataPermission dataScope, LoginModel loginUser, boolean isMulti, List<Long> userIds) {
|
|
|
|
|
- long startTime = System.currentTimeMillis();
|
|
|
|
|
- log.info("sqlHandle starting.........,startTime:{}",startTime);
|
|
|
|
|
- String fieldSql = dataScope.field();
|
|
|
|
|
- if(!"".equals(dataScope.tableAlias()) && !"*".equals(dataScope.tableAlias())){
|
|
|
|
|
- fieldSql = dataScope.tableAlias()+"."+fieldSql;
|
|
|
|
|
- }
|
|
|
|
|
- StringBuilder buffer = new StringBuilder();
|
|
|
|
|
- if (isMulti) {
|
|
|
|
|
- //处理拼接的sql
|
|
|
|
|
- if (userIds != null && !userIds.isEmpty()) {
|
|
|
|
|
- buffer.append(fieldSql + " in(");
|
|
|
|
|
- for (Long id : userIds) {
|
|
|
|
|
- if (buffer.toString().endsWith("(")) {
|
|
|
|
|
- buffer.append(id);
|
|
|
|
|
- } else {
|
|
|
|
|
- buffer.append(", " + id);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- buffer.append(")");
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- buffer.append(fieldSql+" = "+loginUser.getUserId());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- long endTime = System.currentTimeMillis();
|
|
|
|
|
- long executionTime = (endTime - startTime) / 1000;
|
|
|
|
|
-
|
|
|
|
|
- String result = makeSqlQuery(dataScope.tableAlias(), originalSql, buffer.toString());
|
|
|
|
|
- log.info("sqlHandle end,endTime:{},takes about {} seconds",endTime,executionTime);
|
|
|
|
|
- return result;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 数据权限SQL拼接处理
|
|
|
|
|
- *
|
|
|
|
|
- * @param originalSql
|
|
|
|
|
- * @param injectSql
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- private String makeSqlQuery(String tableAlias, String originalSql, String injectSql) {
|
|
|
|
|
- if (StringUtils.isNotEmpty(injectSql)) {
|
|
|
|
|
- if (!originalSql.contains("1=1") && !originalSql.contains("1 = 1") && StringUtils.isEmpty(tableAlias)) {
|
|
|
|
|
- if (!originalSql.toUpperCase().contains(" WHERE ")) {
|
|
|
|
|
- if (originalSql.toUpperCase().contains(" ORDER BY")) {
|
|
|
|
|
- return originalSql.toUpperCase().replace("ORDER", "WHERE " + injectSql + " ORDER");
|
|
|
|
|
- } else if (originalSql.toUpperCase().contains(" GROUP BY")) {
|
|
|
|
|
- return originalSql.toUpperCase().replace("GROUP", "WHERE " + injectSql + " GROUP");
|
|
|
|
|
- } else {
|
|
|
|
|
- return String.format("%s WHERE %s", originalSql, injectSql);
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- if (originalSql.toUpperCase().contains(" ORDER BY")) {
|
|
|
|
|
- return originalSql.toUpperCase().replace("ORDER", "AND " + injectSql + " ORDER");
|
|
|
|
|
- } else if (originalSql.toUpperCase().contains(" GROUP BY")) {
|
|
|
|
|
- return originalSql.toUpperCase().replace("GROUP", "AND " + injectSql + " GROUP");
|
|
|
|
|
- } else if (originalSql.toUpperCase().contains(" LIMIT")) {
|
|
|
|
|
- return originalSql.toUpperCase().replace("LIMIT", "AND " + injectSql + " LIMIT");
|
|
|
|
|
- } else {
|
|
|
|
|
- return String.format("%s AND %s", originalSql, injectSql);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- if (originalSql.contains("1=1") && originalSql.contains(" " + tableAlias + ".")) {
|
|
|
|
|
- return originalSql.replace("1=1", injectSql);
|
|
|
|
|
- }
|
|
|
|
|
- if (originalSql.contains("1 = 1") && originalSql.contains(" " + tableAlias + ".")) {
|
|
|
|
|
- return originalSql.replace("1 = 1", injectSql);
|
|
|
|
|
- }
|
|
|
|
|
- if ((originalSql.contains("1=1") || originalSql.contains("1 = 1")) && tableAlias.equals("*")) {
|
|
|
|
|
- originalSql = originalSql.replace("1=1", injectSql);
|
|
|
|
|
- return originalSql.replace("1 = 1", injectSql);
|
|
|
|
|
- }
|
|
|
|
|
- return originalSql;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return originalSql;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 权限注解
|
|
|
|
|
- * @param strap
|
|
|
|
|
- * @param loginUser
|
|
|
|
|
- * @param session
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- private Map<String, DataPermission> getDataPermissionBySession(long strap, LoginModel loginUser, HttpSession session){
|
|
|
|
|
- Map<String, DataPermission> map = new HashMap<>();
|
|
|
|
|
- for (int i=0;i<10;i++) {
|
|
|
|
|
- String key = loginUser.getToken()+"_"+strap+"_"+loginUser.getUserId();
|
|
|
|
|
- DataPermission permission = (DataPermission) session.getAttribute(key);
|
|
|
|
|
- if (permission != null) {
|
|
|
|
|
- map.put(key, permission);
|
|
|
|
|
- return map;
|
|
|
|
|
- }
|
|
|
|
|
- strap = strap + 100;
|
|
|
|
|
- }
|
|
|
|
|
- return map;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 部门/部门及以下用户权限实体
|
|
|
|
|
- * @param session
|
|
|
|
|
- * @param loginUser
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- private SysDeptUser getDeptUser(HttpSession session, LoginModel loginUser) {
|
|
|
|
|
- String deptKey = loginUser.getToken() + "_" + loginUser.getDeptId();
|
|
|
|
|
- return (SysDeptUser) session.getAttribute(deptKey);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 自定义数据权限角色用户
|
|
|
|
|
- * @param session
|
|
|
|
|
- * @param token
|
|
|
|
|
- * @param roleId
|
|
|
|
|
- * @return
|
|
|
|
|
- */
|
|
|
|
|
- private List<Long> getCustomRoleUserIds(HttpSession session, String token, Long roleId) {
|
|
|
|
|
- String key = token + "_" + roleId;
|
|
|
|
|
- return (List<Long>) session.getAttribute(key);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|