Browse Source

优化权限

zhouhao 6 years ago
parent
commit
cf20178cfb
17 changed files with 474 additions and 23 deletions
  1. 1 3
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/DefaultAopMethodAuthorizeDefinitionParser.java
  2. 1 0
      hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java
  3. 4 0
      hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/RecordCreationEntity.java
  4. 7 3
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-api/src/main/java/org/hswebframework/web/entity/organizational/OrganizationalEntity.java
  5. 4 3
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-api/src/main/java/org/hswebframework/web/entity/organizational/PersonEntity.java
  6. 12 0
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/OrganizationalAuthorizationAutoConfiguration.java
  7. 4 0
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/DepartmentAttachEntity.java
  8. 4 0
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/DistrictAttachEntity.java
  9. 4 0
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/OrgAttachEntity.java
  10. 4 0
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/PersonAttachEntity.java
  11. 4 0
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/PositionAttachEntity.java
  12. 30 0
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeByUserDataAccessConfig.java
  13. 35 0
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeByUserDataAccessConfigConvert.java
  14. 16 11
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/AbstractScopeDataAccessHandler.java
  15. 0 2
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/CustomScopeHandler.java
  16. 342 0
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/ScopeByUserHandler.java
  17. 2 1
      hsweb-system/hsweb-system-organizational/hsweb-system-organizational-web/src/main/java/org/hswebframework/web/controller/organizational/PersonController.java

+ 1 - 3
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/aop/DefaultAopMethodAuthorizeDefinitionParser.java

@@ -100,15 +100,13 @@ public class DefaultAopMethodAuthorizeDefinitionParser implements AopMethodAutho
 
         authorizeDefinition.put(expression);
 
-        if (methodAuth != null) {
-            authorizeDefinition.put(methodAuth.dataAccess());
-        }
         authorizeDefinition.put(classDataAccess);
 
         authorizeDefinition.put(methodDataAccess);
 
         if (authorizeDefinition.getPermissionDescription().length == 0) {
             if (classAuth != null) {
+                authorizeDefinition.put(classAuth.dataAccess());
                 String[] desc = classAuth.description();
                 if (desc.length > 0) {
                     authorizeDefinition.setPermissionDescription(desc);

+ 1 - 0
hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java

@@ -82,6 +82,7 @@ public class DefaultBasicAuthorizeDefinition implements AopAuthorizeDefinition {
         }
         message = authorize.message();
         phased = authorize.phased();
+        put(authorize.dataAccess());
     }
 
     public void put(RequiresExpression expression) {

+ 4 - 0
hsweb-commons/hsweb-commons-entity/src/main/java/org/hswebframework/web/commons/entity/RecordCreationEntity.java

@@ -23,4 +23,8 @@ public interface RecordCreationEntity extends Entity {
     default void setCreateTimeNow() {
         setCreateTime(System.currentTimeMillis());
     }
+
+    default String getCreatorIdProperty() {
+        return creatorId;
+    }
 }

+ 7 - 3
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-api/src/main/java/org/hswebframework/web/entity/organizational/OrganizationalEntity.java

@@ -1,18 +1,18 @@
 /*
  *  Copyright 2016 http://www.hswebframework.org
- *  
+ *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
  *  You may obtain a copy of the License at
  *
  *        http://www.apache.org/licenses/LICENSE-2.0
- *  
+ *
  *  Unless required by applicable law or agreed to in writing, software
  *  distributed under the License is distributed on an "AS IS" BASIS,
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
- *  
+ *
  */
 package org.hswebframework.web.entity.organizational;
 
@@ -125,4 +125,8 @@ public interface OrganizationalEntity extends TreeSortSupportEntity<String>, Dis
     default void setOrgId(String orgId) {
         setId(orgId);
     }
+
+    default String getOrgIdProperty() {
+        return "id";
+    }
 }

+ 4 - 3
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-api/src/main/java/org/hswebframework/web/entity/organizational/PersonEntity.java

@@ -1,22 +1,23 @@
 /*
  *  Copyright 2016 http://www.hswebframework.org
- *  
+ *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
  *  You may obtain a copy of the License at
  *
  *        http://www.apache.org/licenses/LICENSE-2.0
- *  
+ *
  *  Unless required by applicable law or agreed to in writing, software
  *  distributed under the License is distributed on an "AS IS" BASIS,
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
- *  
+ *
  */
 package org.hswebframework.web.entity.organizational;
 
 import org.hswebframework.web.commons.entity.GenericEntity;
+import org.hswebframework.web.commons.entity.RecordCreationEntity;
 
 /**
  * 人员 实体

+ 12 - 0
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/OrganizationalAuthorizationAutoConfiguration.java

@@ -65,6 +65,18 @@ public class OrganizationalAuthorizationAutoConfiguration implements BeanPostPro
         return new CustomScopeDataAccessConfigConvert();
     }
 
+    @Bean
+    @ConditionalOnMissingBean(ScopeByUserDataAccessConfigConvert.class)
+    public ScopeByUserDataAccessConfigConvert scopeByUserDataAccessConfigConvert() {
+        return new ScopeByUserDataAccessConfigConvert();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean(ScopeByUserHandler.class)
+    public ScopeByUserHandler scopeByUserHandler() {
+        return new ScopeByUserHandler();
+    }
+
     @Override
     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
         return bean;

+ 4 - 0
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/DepartmentAttachEntity.java

@@ -21,4 +21,8 @@ public interface DepartmentAttachEntity extends Entity {
     String getDepartmentId();
 
     void setDepartmentId(String departmentId);
+
+    default String getDepartmentIdProperty() {
+        return departmentId;
+    }
 }

+ 4 - 0
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/DistrictAttachEntity.java

@@ -11,4 +11,8 @@ public interface DistrictAttachEntity extends Entity {
     String getDistrictId();
 
     void setDistrictId(String districtId);
+
+    default String getDistrictIdProperty() {
+        return districtId;
+    }
 }

+ 4 - 0
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/OrgAttachEntity.java

@@ -14,4 +14,8 @@ public interface OrgAttachEntity extends Entity {
     String getOrgId();
 
     void setOrgId(String orgId);
+
+    default String getOrgIdProperty() {
+        return orgId;
+    }
 }

+ 4 - 0
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/PersonAttachEntity.java

@@ -12,4 +12,8 @@ public interface PersonAttachEntity  extends Entity {
     String getPersonId();
 
     void setPersonId(String personId);
+
+    default String getPersonIdProperty() {
+        return personId;
+    }
 }

+ 4 - 0
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/access/PositionAttachEntity.java

@@ -11,4 +11,8 @@ public interface PositionAttachEntity extends Entity {
     String getPositionId();
 
     void setPositionId(String positionId);
+
+    default String getPositionIdProperty() {
+        return positionId;
+    }
 }

+ 30 - 0
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeByUserDataAccessConfig.java

@@ -0,0 +1,30 @@
+package org.hswebframework.web.organizational.authorization.simple;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.hswebframework.web.authorization.simple.AbstractDataAccessConfig;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author zhouhao
+ * @since 3.0.5
+ */
+@Getter
+@Setter
+public class ScopeByUserDataAccessConfig extends AbstractDataAccessConfig {
+
+    private static final long serialVersionUID = 6678003761927318688L;
+
+    private String scopeType;
+
+    private Set<String> scope;
+
+    private boolean children;
+
+    @Override
+    public String getType() {
+        return "SCOPE_BY_USER";
+    }
+}

+ 35 - 0
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/ScopeByUserDataAccessConfigConvert.java

@@ -0,0 +1,35 @@
+package org.hswebframework.web.organizational.authorization.simple;
+
+import com.alibaba.fastjson.JSON;
+import lombok.Getter;
+import lombok.Setter;
+import org.hswebframework.web.authorization.access.DataAccessConfig;
+import org.hswebframework.web.authorization.simple.AbstractDataAccessConfig;
+import org.hswebframework.web.authorization.simple.builder.DataAccessConfigConvert;
+import org.springframework.util.StringUtils;
+
+import java.util.List;
+
+/**
+ * @author zhouhao
+ * @since 3.0.5
+ */
+@Getter
+@Setter
+public class ScopeByUserDataAccessConfigConvert implements DataAccessConfigConvert {
+
+    @Override
+    public boolean isSupport(String type, String action, String config) {
+        return "SCOPE_BY_USER".equalsIgnoreCase(type);
+    }
+
+    @Override
+    public DataAccessConfig convert(String type, String action, String config) {
+        if (StringUtils.isEmpty(config)) {
+            config = "{}";
+        }
+        ScopeByUserDataAccessConfig dataAccessConfig = JSON.parseObject(config, ScopeByUserDataAccessConfig.class);
+        dataAccessConfig.setAction(action);
+        return dataAccessConfig;
+    }
+}

+ 16 - 11
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/AbstractScopeDataAccessHandler.java

@@ -84,11 +84,10 @@ public abstract class AbstractScopeDataAccessHandler<E> implements DataAccessHan
             logger.warn("existing many scope :{} , try use config.", scope);
         }
         if (scope != null) {
-            String finalScopeId = scope;
             context.getParamContext().getParams().values().stream()
                     .filter(getEntityClass()::isInstance)
                     .map(getEntityClass()::cast)
-                    .forEach(entity -> applyScopeProperty(entity, finalScopeId));
+                    .forEach(entity -> applyScopeProperty(entity, scope));
         } else {
             logger.warn("scope is null!");
         }
@@ -153,18 +152,24 @@ public abstract class AbstractScopeDataAccessHandler<E> implements DataAccessHan
             if (logger.isDebugEnabled()) {
                 logger.debug("try rebuild query param ...");
             }
-            QueryParamEntity queryParamEntity = ((QueryParamEntity) entity);
+
             //重构查询条件
             //如: 旧的条件为 where name =? or name = ?
             //重构后为: where org_id in(?,?) and (name = ? or name = ?)
-            List<Term> oldParam = queryParamEntity.getTerms();
-            //清空旧的查询条件
-            queryParamEntity.setTerms(new ArrayList<>());
-            //添加一个查询条件
-            queryParamEntity
-                    .addTerm(createQueryTerm(scope, context))
-                    //客户端提交的参数 作为嵌套参数
-                    .nest().setTerms(oldParam);
+            QueryParamEntity queryParamEntity = ((QueryParamEntity) entity);
+            queryParamEntity.toNestQuery(query-> query.accept(createQueryTerm(scope, context)));
+
+//            //重构查询条件
+//            //如: 旧的条件为 where name =? or name = ?
+//            //重构后为: where org_id in(?,?) and (name = ? or name = ?)
+//            List<Term> oldParam = queryParamEntity.getTerms();
+//            //清空旧的查询条件
+//            queryParamEntity.setTerms(new ArrayList<>());
+//            //添加一个查询条件
+//            queryParamEntity
+//                    .addTerm(createQueryTerm(scope, context))
+//                    //客户端提交的参数 作为嵌套参数
+//                    .nest().setTerms(oldParam);
         } else {
             logger.warn("try validate query access,but entity not support, QueryParamEntity support now!");
         }

+ 0 - 2
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/CustomScopeHandler.java

@@ -12,8 +12,6 @@ import java.util.HashSet;
 import java.util.List;
 
 /**
- * TODO 完成注释
- *
  * @author zhouhao
  */
 public class CustomScopeHandler implements DataAccessHandler {

+ 342 - 0
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-authorization/src/main/java/org/hswebframework/web/organizational/authorization/simple/handler/ScopeByUserHandler.java

@@ -0,0 +1,342 @@
+package org.hswebframework.web.organizational.authorization.simple.handler;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.hswebframework.ezorm.core.dsl.Query;
+import org.hswebframework.web.authorization.Authentication;
+import org.hswebframework.web.authorization.Permission;
+import org.hswebframework.web.authorization.access.DataAccessConfig;
+import org.hswebframework.web.authorization.access.DataAccessHandler;
+import org.hswebframework.web.authorization.define.AuthorizingContext;
+import org.hswebframework.web.authorization.define.Phased;
+import org.hswebframework.web.authorization.exception.AccessDenyException;
+import org.hswebframework.web.authorization.exception.UnAuthorizedException;
+import org.hswebframework.web.bean.FastBeanCopier;
+import org.hswebframework.web.commons.entity.Entity;
+import org.hswebframework.web.commons.entity.RecordCreationEntity;
+import org.hswebframework.web.commons.entity.factory.EntityFactory;
+import org.hswebframework.web.commons.entity.param.QueryParamEntity;
+import org.hswebframework.web.controller.QueryController;
+import org.hswebframework.web.controller.message.ResponseMessage;
+import org.hswebframework.web.organizational.authorization.PersonnelAuthentication;
+import org.hswebframework.web.organizational.authorization.PersonnelAuthenticationHolder;
+import org.hswebframework.web.organizational.authorization.access.*;
+import org.hswebframework.web.organizational.authorization.simple.ScopeByUserDataAccessConfig;
+import org.hswebframework.web.service.QueryService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.ClassUtils;
+import org.springframework.util.ReflectionUtils;
+
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.*;
+
+/**
+ * @author zhouhao
+ * @since 3.0.5
+ */
+@Slf4j
+@SuppressWarnings("all")
+public class ScopeByUserHandler implements DataAccessHandler {
+
+    @Autowired
+    private EntityFactory entityFactory;
+
+    @Override
+    public boolean isSupport(DataAccessConfig access) {
+        return access instanceof ScopeByUserDataAccessConfig;
+    }
+
+    @Override
+    public boolean handle(DataAccessConfig access, AuthorizingContext context) {
+        ScopeByUserDataAccessConfig scope = ((ScopeByUserDataAccessConfig) access);
+        switch (access.getAction()) {
+            case Permission.ACTION_QUERY:
+            case Permission.ACTION_GET:
+                return doQueryAccess(scope, context);
+            case Permission.ACTION_ADD:
+            case Permission.ACTION_UPDATE:
+            default:
+                return doUpdateAccess(scope, context);
+        }
+    }
+
+    protected boolean doUpdateAccess(ScopeByUserDataAccessConfig config, AuthorizingContext context) {
+        //获取注解
+        Object id = context.getParamContext()
+                .<String>getParameter(context.getDefinition().getDataAccessDefinition().getIdParameterName())
+                .orElse(null);
+        if (id == null) {
+            return true;
+        }
+        PersonnelAuthentication authentication = PersonnelAuthentication.current().orElseThrow(UnAuthorizedException::new);
+        ScopeInfo scopeInfo = getScope(config, authentication);
+        if (scopeInfo.isEmpty()) {
+            return false;
+        }
+        Object controller = context.getParamContext().getTarget();
+        QueryService<Object, Object> queryService = null;
+
+        if (controller instanceof QueryController) {
+            queryService = ((QueryController<Object, Object, Entity>) controller).getService();
+        } else {
+            Method getService = ReflectionUtils.findMethod(controller.getClass(), "getService");
+            if (getService != null) {
+                try {
+                    Object service = ReflectionUtils.invokeMethod(getService, controller);
+                    if (service instanceof QueryService) {
+                        queryService = ((QueryService) service);
+                    }
+                } catch (Exception ignore) {
+
+                }
+            }
+        }
+        if (queryService != null) {
+            ControllerCache controllerCache = getControllerCache(config, context);
+            Object entity = queryService.selectByPk(id);
+            if (null != entity) {
+                String targetId = controllerCache.targetIdGetter.apply(entity);
+                log.debug("执行数据权限控制,scope:{},target:{}", scopeInfo.scope, targetId);
+                if (targetId == null) {
+                    return true;
+                }
+                return scopeInfo.scope.contains(controllerCache.targetIdGetter.apply(entity));
+            }
+        } else {
+            log.warn("Controller没有实现任何通用CURD功能,无法进行数据权限控制!");
+        }
+        return true;
+
+    }
+
+    private ScopeInfo getScope(ScopeByUserDataAccessConfig config, PersonnelAuthentication authentication) {
+        String termType = null;
+        Set<String> scope = null;
+        ScopeInfo scopeInfo = new ScopeInfo();
+        if (authentication == null) {
+            return scopeInfo;
+        }
+        Consumer<Query<?, QueryParamEntity>> consumer;
+
+        switch (config.getScopeType()) {
+            case DataAccessType.ORG_SCOPE:
+                termType = "user-in-org";
+                scope = authentication.getRootOrgId();
+                break;
+            case DataAccessType.DEPARTMENT_SCOPE:
+                termType = "user-in-department";
+                scope = authentication.getRootDepartmentId();
+                break;
+            case DataAccessType.POSITION_SCOPE:
+                termType = "user-in-position";
+                break;
+            case DataAccessType.DISTRICT_SCOPE:
+                termType = "user-in-dist";
+                scope = authentication.getRootDistrictId();
+                break;
+            case "CUSTOM_SCOPE_ORG":
+                termType = "user-in-org";
+                scope = config.getScope();
+                break;
+            case "CUSTOM_SCOPE_DEPT":
+                termType = "user-in-department";
+                scope = config.getScope();
+                break;
+            case "CUSTOM_SCOPE_DIST":
+                termType = "user-in-dist";
+                scope = config.getScope();
+                break;
+            default:
+                log.warn("不支持的数据权限范围:{}", config.getScopeType());
+        }
+        if (termType == null) {
+            return scopeInfo;
+        }
+        scopeInfo.scope = scope;
+        scopeInfo.termType = termType;
+        if (config.isChildren()) {
+            scopeInfo.termType = termType + termType.concat("-child");
+        }
+        return scopeInfo;
+
+    }
+
+    class ScopeInfo {
+        String termType;
+
+        Set<String> scope;
+
+        Consumer<Query<?, QueryParamEntity>> notUserConsumer;
+
+        public boolean isEmpty() {
+            return termType == null || scope == null || scope.isEmpty();
+        }
+    }
+
+    static Function<Object, String> defaultTargetIdGetter = entity -> {
+        Map<String, String> userInfo = FastBeanCopier.copy(entity, new HashMap<>(),
+                FastBeanCopier.include("creatorId"));
+        return userInfo.get("creatorId");
+    };
+
+    static BiConsumer<Query<?, QueryParamEntity>, ScopeInfo> defaultQueryConsumer = (query, scopeInfo) -> {
+        query.and("creatorId", scopeInfo.termType, scopeInfo.scope);
+    };
+    static Function<AuthorizingContext, Set<String>>         defaultScopeGetter   = context -> {
+        return Collections.singleton(context.getAuthentication().getUser().getId());
+    };
+
+    private <E> Function<Object, String> createGetter(Class<E> type, Function<E, String> getter) {
+        return entity -> {
+            if (type.isInstance(entity)) {
+                return getter.apply(((E) entity));
+            }
+            return defaultTargetIdGetter.apply(entity);
+        };
+    }
+
+    static Map<Class, String> cache = new ConcurrentHashMap<>();
+
+    protected <T> String getControlProperty(Class type, Function<T, String> function) {
+        return cache.computeIfAbsent(type, t -> {
+            return function.apply((T) entityFactory.newInstance(type));
+        });
+    }
+
+    class ControllerCache {
+        Function<Object, String> targetIdGetter = defaultTargetIdGetter;
+
+        BiConsumer<Query<?, QueryParamEntity>, ScopeInfo> queryConsumer = defaultQueryConsumer;
+
+        Function<AuthorizingContext, Set<String>> scopeGetter = defaultScopeGetter;
+    }
+
+    @EqualsAndHashCode
+    @Getter
+    @Setter
+    class CacheKey {
+        private String className;
+
+        private boolean children;
+
+        private String type;
+    }
+
+    static Map<CacheKey, ControllerCache> cacheMap = new ConcurrentHashMap<>();
+
+
+    private ControllerCache getControllerCache(ScopeByUserDataAccessConfig config, AuthorizingContext context) {
+        CacheKey cacheKey = new CacheKey();
+        cacheKey.children = config.isChildren();
+        cacheKey.className = ClassUtils.getUserClass(context.getParamContext().getTarget().getClass()).getName();
+        cacheKey.type = config.getScopeType();
+        return cacheMap.computeIfAbsent(cacheKey, key -> {
+            ControllerCache controllerCache = new ControllerCache();
+            if (context.getParamContext().getTarget() instanceof QueryController) {
+                boolean children = config.isChildren();
+                Class controller = ClassUtils.getUserClass(context.getParamContext().getTarget().getClass());
+                Class entityClass = org.hswebframework.utils.ClassUtils.getGenericType(controller, 0);
+                if (RecordCreationEntity.class.isAssignableFrom(entityClass)) {
+                    controllerCache.targetIdGetter = createGetter(RecordCreationEntity.class, RecordCreationEntity::getCreatorId);
+                    controllerCache.queryConsumer = (query, scopeInfo) -> {
+                        query.and(getControlProperty(entityClass, RecordCreationEntity::getCreatorIdProperty), scopeInfo.termType, scopeInfo.scope);
+                    };
+                } else if (OrgAttachEntity.class.isAssignableFrom(entityClass) && config.getScopeType().contains("ORG")) {
+                    controllerCache.targetIdGetter = createGetter(OrgAttachEntity.class, OrgAttachEntity::getOrgId);
+                    controllerCache.queryConsumer = (query, scopeInfo) -> {
+                        query.and(getControlProperty(entityClass, OrgAttachEntity::getOrgIdProperty), children ? "org-child-in" : "org-in", scopeInfo.scope);
+                    };
+                } else if (DepartmentAttachEntity.class.isAssignableFrom(entityClass) && config.getScopeType().contains("DEPT")) {
+                    controllerCache.targetIdGetter = createGetter(DepartmentAttachEntity.class, DepartmentAttachEntity::getDepartmentId);
+                    controllerCache.queryConsumer = (query, scopeInfo) -> {
+                        query.and(getControlProperty(entityClass, DepartmentAttachEntity::getDepartmentIdProperty), children ? "dept-child-in" : "dept-in", scopeInfo.scope);
+                    };
+                } else if (PositionAttachEntity.class.isAssignableFrom(entityClass) && config.getScopeType().contains("POS")) {
+                    controllerCache.targetIdGetter = createGetter(PositionAttachEntity.class, PositionAttachEntity::getPositionId);
+                    controllerCache.queryConsumer = (query, scopeInfo) -> {
+                        query.and(getControlProperty(entityClass, PositionAttachEntity::getPositionIdProperty), children ? "pos-child-in" : "pos-in", scopeInfo.scope);
+                    };
+                } else if (DistrictAttachEntity.class.isAssignableFrom(entityClass) && config.getScopeType().contains("DIST")) {
+                    controllerCache.targetIdGetter = createGetter(DistrictAttachEntity.class, DistrictAttachEntity::getDistrictId);
+                    controllerCache.queryConsumer = (query, scopeInfo) -> {
+                        query.and(getControlProperty(entityClass, DistrictAttachEntity::getDistrictIdProperty), children ? "dist-child-in" : "dist-in", scopeInfo.scope);
+                    };
+                } else {
+                    String userIdField = getUserField(entityClass);
+                    controllerCache.targetIdGetter = entity -> {
+                        Map<String, String> userInfo = FastBeanCopier.copy(entity, new HashMap<>(),
+                                FastBeanCopier.include(userIdField));
+                        return userInfo.get(userIdField);
+                    };
+                    controllerCache.queryConsumer = (query, scopeInfo) -> {
+                        query.and(userIdField, scopeInfo.termType, scopeInfo.scope);
+                    };
+                }
+            }
+            return controllerCache;
+        });
+    }
+
+    protected boolean doQueryAccess(ScopeByUserDataAccessConfig config, AuthorizingContext context) {
+        PersonnelAuthentication authentication = PersonnelAuthentication
+                .current()
+                .orElseThrow(AccessDenyException::new);
+        ScopeInfo scopeInfo = getScope(config, authentication);
+        if (scopeInfo.isEmpty()) {
+            return false;
+        }
+        ControllerCache controllerCache = getControllerCache(config, context);
+
+        //如果是执行后
+        if (context.getDefinition().getDataAccessDefinition().getPhased() == Phased.after) {
+            Object result = context.getParamContext().getInvokeResult();
+            if (result == null) {
+                return true;
+            }
+            if (result instanceof ResponseEntity) {
+                result = ((ResponseEntity) result).getBody();
+            }
+            if (result instanceof ResponseMessage) {
+                result = ((ResponseMessage) result).getResult();
+            }
+            String value = controllerCache.targetIdGetter.apply(result);
+            log.debug("执行数据权限控制,scope:{},target:{}", scopeInfo.scope, value);
+            if (value == null) {
+                return true;
+            }
+            return scopeInfo.scope.contains(value);
+        }
+
+        Entity entity = context.getParamContext()
+                .getParams()
+                .values()
+                .stream()
+                .filter(Entity.class::isInstance)
+                .map(Entity.class::cast)
+                .findAny()
+                .orElse(null);
+
+        if (entity instanceof QueryParamEntity) {
+            QueryParamEntity param = ((QueryParamEntity) entity);
+            param.toNestQuery(query -> {
+                log.debug("执行查询数据权限控制,scope:{}", scopeInfo.scope);
+                controllerCache.queryConsumer.accept(query, scopeInfo);
+            });
+        }
+        return true;
+    }
+
+    public String getUserField(Class type) {
+
+        if (ReflectionUtils.findField(type, "userId") != null) {
+            return "userId";
+        }
+
+        return "creatorId";
+    }
+}

+ 2 - 1
hsweb-system/hsweb-system-organizational/hsweb-system-organizational-web/src/main/java/org/hswebframework/web/controller/organizational/PersonController.java

@@ -22,6 +22,7 @@ import io.swagger.annotations.ApiOperation;
 import org.hswebframework.web.NotFoundException;
 import org.hswebframework.web.authorization.Permission;
 import org.hswebframework.web.authorization.annotation.Authorize;
+import org.hswebframework.web.authorization.annotation.RequiresDataAccess;
 import org.hswebframework.web.commons.entity.PagerResult;
 import org.hswebframework.web.commons.entity.param.QueryParamEntity;
 import org.hswebframework.web.controller.SimpleGenericEntityController;
@@ -43,7 +44,7 @@ import java.util.List;
  */
 @RestController
 @RequestMapping("${hsweb.web.mappings.person:person}")
-@Authorize(permission = "person",description = "人员管理")
+@Authorize(permission = "person",description = "人员管理",dataAccess = @RequiresDataAccess)
 @Api(value = "人员管理",tags = "组织架构-人员管理")
 public class PersonController implements SimpleGenericEntityController<PersonEntity, String, QueryParamEntity> {