feat: api权限验证基本功能以及仪表板增删改权限demo

This commit is contained in:
fit2cloud-chenyw 2022-01-25 14:35:07 +08:00
parent 5c2ae56184
commit 71f3d463c4
22 changed files with 861 additions and 39 deletions

View File

@ -22,6 +22,12 @@
<dependencies> <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>

View File

@ -0,0 +1,22 @@
package io.dataease.auth.annotation;
import io.dataease.commons.constants.DePermissionType;
import io.dataease.commons.constants.ResourceAuthLevel;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DePermission {
DePermissionType type();
ResourceAuthLevel level() default ResourceAuthLevel.COMMON_LEVEL_USE;
String value() default "";
int paramIndex() default 0;
}

View File

@ -0,0 +1,21 @@
package io.dataease.auth.annotation;
import org.apache.shiro.authz.annotation.Logical;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DePermissions {
DePermission[] value();
Logical logical() default Logical.AND;
}

View File

@ -0,0 +1,187 @@
package io.dataease.auth.aop;
import io.dataease.auth.annotation.DePermission;
import io.dataease.auth.annotation.DePermissions;
import io.dataease.auth.entity.AuthItem;
import io.dataease.commons.utils.AuthUtils;
import io.dataease.commons.utils.LogUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.authz.annotation.Logical;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;
@Aspect
@Component
public class DePermissionAnnotationHandler {
@Around(value = "@annotation(io.dataease.auth.annotation.DePermissions)")
public Object PermissionsAround(ProceedingJoinPoint point) {
try {
MethodSignature ms = (MethodSignature) point.getSignature();
Method method = ms.getMethod();
DePermissions annotation = method.getAnnotation(DePermissions.class);
Logical logical = annotation.logical();
DePermission[] dePermissions = annotation.value();
Object[] args = point.getArgs();
if (logical == Logical.AND) {
for (int i = 0; i < dePermissions.length; i++) {
DePermission permission = dePermissions[i];
boolean currentAccess = access(args[permission.paramIndex()], permission, 0);
if (!currentAccess) {
return null;
}
}
} else {
List<Exception> exceptions = new ArrayList<>();
Boolean someAccess = false;
for (int i = 0; i < dePermissions.length; i++) {
DePermission permission = dePermissions[i];
try{
boolean currentAccess = access(args[permission.paramIndex()], permission, 0);
if (currentAccess) {
someAccess = true;
break;
}
}catch (Exception e) {
exceptions.add(e);
}
}
if (!someAccess) {
throw exceptions.get(0);
}
}
return point.proceed(point.getArgs());
} catch (Throwable throwable) {
LogUtil.error(throwable.getMessage(), throwable);
throw new RuntimeException(throwable);
}
}
@Around(value = "@annotation(io.dataease.auth.annotation.DePermission)")
public Object PermissionAround(ProceedingJoinPoint point) {
try {
MethodSignature ms = (MethodSignature) point.getSignature();
Method method = ms.getMethod();
DePermission annotation = method.getAnnotation(DePermission.class);
Object arg = point.getArgs()[annotation.paramIndex()];
if (access(arg, annotation, 0)) {
return point.proceed(point.getArgs());
}
return false;
} catch (Throwable throwable) {
LogUtil.error(throwable.getMessage(), throwable);
throw new RuntimeException(throwable);
}
}
private Boolean access(Object arg, DePermission annotation, int layer) throws Exception {
if (ObjectUtils.isEmpty(arg)) return true;
String type = annotation.type().name().toLowerCase();
String value = annotation.value();
Integer requireLevel = annotation.level().getLevel();
Set<String> resourceIds = AuthUtils.permissionByType(type).stream().filter(
item -> item.getLevel() >= requireLevel
).map(AuthItem::getAuthSource).collect(Collectors.toSet());
Class<?> parameterType = arg.getClass();
if (parameterType.isPrimitive() || isWrapClass(parameterType) || isString(parameterType)) {
boolean permissionValid = resourceIds.contains(arg);
if (permissionValid) return true;
throw new UnauthorizedException("Subject does not have permission[" + annotation.level().name() +":"+ annotation.type() + ":" + arg + "]");
} else if (isArray(parameterType)) {
for (int i = 0; i < Array.getLength(arg); i++) {
Object o = Array.get(arg, i);
if (!access(o, annotation, layer)) {
return false;
}
}
} else if (isCollection(parameterType)) {
Object[] array = ((Collection) arg).toArray();
for (int i = 0; i < array.length; i++) {
Object o = array[i];
if (!access(o, annotation, layer)) {
return false;
}
}
} else if (isMap(parameterType)) {
Map<String, Object> argMap = (Map) arg;
String[] values = value.split(".");
Object o = argMap.get(values[layer]);
return access(o, annotation, ++layer);
} else {
//当作自定义类处理
String[] values = value.split("u002E");
String fieldName = values[layer];
Object fieldValue = getFieldValue(arg, fieldName);
return access(fieldValue, annotation, ++layer);
}
return true;
}
private Object getFieldValue(Object o, String fieldName) throws Exception{
Class<?> aClass = o.getClass();
while (null != aClass.getSuperclass()) {
Field[] declaredFields = aClass.getDeclaredFields();
for (int i = 0; i < declaredFields.length; i++) {
Field field = declaredFields[i];
String name = field.getName();
if (StringUtils.equals(name, fieldName)) {
field.setAccessible(true);
return field.get(o);
}
}
aClass = aClass.getSuperclass();
}
throw new NoSuchFieldException(fieldName);
}
private final static String[] wrapClasies = {
"java.lang.Boolean",
"java.lang.Character",
"java.lang.Integer",
"java.lang.Byte",
"java.lang.Short",
"java.lang.Long",
"java.lang.Float",
"java.lang.Double",
};
private Boolean isString(Class clz) {
return StringUtils.equals("java.lang.String", clz.getName());
}
private Boolean isArray(Class clz) {
return clz.isArray();
}
private Boolean isCollection(Class clz) {
return Collection.class.isAssignableFrom(clz);
}
private Boolean isMap(Class clz) {
return Map.class.isAssignableFrom(clz);
}
private Boolean isWrapClass(Class clz) {
return Arrays.stream(wrapClasies).anyMatch(item -> StringUtils.equals(item, clz.getName()));
}
}

View File

@ -21,6 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -44,11 +45,11 @@ public class F2CRealm extends AuthorizingRealm {
//验证资源权限 //验证资源权限
@Override @Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
Long userId = JWTUtils.tokenInfoByToken(principals.toString()).getUserId(); CurrentUserDto userDto = (CurrentUserDto)principals.getPrimaryPrincipal();
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
Set<String> role = new HashSet<>(authUserService.roles(userId)); Set<String> role = new HashSet<>(userDto.getRoles().stream().map(item -> ( item.getId() + "")).collect(Collectors.toSet()));
simpleAuthorizationInfo.addRoles(role); simpleAuthorizationInfo.addRoles(role);
Set<String> permission = new HashSet<>(authUserService.permissions(userId)); Set<String> permission = new HashSet<>(userDto.getPermissions());
simpleAuthorizationInfo.addStringPermissions(permission); simpleAuthorizationInfo.addStringPermissions(permission);
return simpleAuthorizationInfo; return simpleAuthorizationInfo;
} }

View File

@ -0,0 +1,39 @@
package io.dataease.auth.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Objects;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class AuthItem implements Serializable {
private static final long serialVersionUID = 7909546616315767531L;
private String authSource;
private Integer level;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AuthItem authItem = (AuthItem) o;
return Objects.equals(authSource, authItem.authSource) &&
Objects.equals(level, authItem.level);
}
@Override
public int hashCode() {
return Objects.hash(authSource, level);
}
}

View File

@ -1,7 +1,9 @@
package io.dataease.auth.service; package io.dataease.auth.service;
import io.dataease.auth.entity.AuthItem;
import io.dataease.commons.model.AuthURD; import io.dataease.commons.model.AuthURD;
import java.util.List;
import java.util.Set; import java.util.Set;
public interface ExtAuthService { public interface ExtAuthService {
@ -9,4 +11,22 @@ public interface ExtAuthService {
Set<Long> userIdsByRD(AuthURD request); Set<Long> userIdsByRD(AuthURD request);
AuthURD resourceTarget(String resourceId); AuthURD resourceTarget(String resourceId);
List<AuthItem> dataSourceIdByUser(Long userId);
List<AuthItem> dataSetIdByUser(Long userId);
List<AuthItem> panelIdByUser(Long userId);
List<AuthItem> dataSourceIdByRole(Long roleId);
List<AuthItem> dataSetIdByRole(Long roleId);
List<AuthItem> panelIdByRole(Long roleId);
List<AuthItem> dataSourceIdByDept(Long deptId);
List<AuthItem> dataSetIdByDept(Long deptId);
List<AuthItem> panelIdByDept(Long deptId);
void clearUserResource(Long userId);
void clearDeptResource(Long deptId);
void clearRoleResource(Long roleId);
} }

View File

@ -1,22 +1,28 @@
package io.dataease.auth.service.impl; package io.dataease.auth.service.impl;
import io.dataease.auth.entity.AuthItem;
import io.dataease.auth.service.ExtAuthService; import io.dataease.auth.service.ExtAuthService;
import io.dataease.base.domain.SysAuth; import io.dataease.base.domain.SysAuth;
import io.dataease.base.mapper.ext.ExtAuthMapper; import io.dataease.base.mapper.ext.ExtAuthMapper;
import io.dataease.commons.constants.AuthConstants;
import io.dataease.commons.model.AuthURD; import io.dataease.commons.model.AuthURD;
import io.dataease.commons.utils.LogUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.HashSet; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
public class ExtAuthServiceImpl implements ExtAuthService { public class ExtAuthServiceImpl implements ExtAuthService {
private static final List<AuthItem> emptyResult = new ArrayList();
@Resource @Resource
private ExtAuthMapper extAuthMapper; private ExtAuthMapper extAuthMapper;
@ -55,4 +61,89 @@ public class ExtAuthServiceImpl implements ExtAuthService {
} }
return authURD; return authURD;
} }
@Cacheable(value = AuthConstants.USER_LINK_NAME, key = "'user' + #userId")
@Override
public List<AuthItem> dataSourceIdByUser(Long userId) {
return extAuthMapper.dataSourceIdByUser(userId.toString());
}
@Cacheable(value = AuthConstants.USER_DATASET_NAME, key = "'user' + #userId")
@Override
public List<AuthItem> dataSetIdByUser(Long userId) {
return extAuthMapper.dataSetIdByUser(userId.toString());
}
@Cacheable(value = AuthConstants.USER_PANEL_NAME, key = "'user' + #userId")
@Override
public List<AuthItem> panelIdByUser(Long userId) {
return extAuthMapper.panelIdByUser(userId.toString());
}
@Cacheable(value = AuthConstants.ROLE_LINK_NAME, key = "'role' + #roleId")
@Override
public List<AuthItem> dataSourceIdByRole(Long roleId) {
return extAuthMapper.dataSourceIdByRole(roleId.toString());
}
@Cacheable(value = AuthConstants.ROLE_DATASET_NAME, key = "'role' + #roleId")
@Override
public List<AuthItem> dataSetIdByRole(Long roleId) {
return extAuthMapper.dataSetIdByRole(roleId.toString());
}
@Cacheable(value = AuthConstants.ROLE_PANEL_NAME, key = "'role' + #roleId")
@Override
public List<AuthItem> panelIdByRole(Long roleId) {
return extAuthMapper.panelIdByRole(roleId.toString());
}
@Cacheable(value = AuthConstants.DEPT_LINK_NAME, key = "'dept' + #deptId")
@Override
public List<AuthItem> dataSourceIdByDept(Long deptId) {
if (ObjectUtils.isEmpty(deptId)) return emptyResult;
return extAuthMapper.dataSourceIdByDept(deptId.toString());
}
@Cacheable(value = AuthConstants.DEPT_DATASET_NAME, key = "'dept' + #deptId")
@Override
public List<AuthItem> dataSetIdByDept(Long deptId) {
if (ObjectUtils.isEmpty(deptId)) return emptyResult;
return extAuthMapper.dataSetIdByDept(deptId.toString());
}
@Cacheable(value = AuthConstants.DEPT_PANEL_NAME, key = "'dept' + #deptId")
@Override
public List<AuthItem> panelIdByDept(Long deptId) {
if (ObjectUtils.isEmpty(deptId)) return emptyResult;
return extAuthMapper.panelIdByDept(deptId.toString());
}
@Caching(evict = {
@CacheEvict(value = AuthConstants.USER_LINK_NAME, key = "'user' + #userId"),
@CacheEvict(value = AuthConstants.USER_DATASET_NAME, key = "'user' + #userId"),
@CacheEvict(value = AuthConstants.USER_PANEL_NAME, key = "'user' + #userId")
})
public void clearUserResource(Long userId) {
LogUtil.info("all permission resource of user {} is cleanning...", userId);
}
@Caching(evict = {
@CacheEvict(value = AuthConstants.DEPT_LINK_NAME, key = "'dept' + #deptId"),
@CacheEvict(value = AuthConstants.DEPT_DATASET_NAME, key = "'dept' + #deptId"),
@CacheEvict(value = AuthConstants.DEPT_PANEL_NAME, key = "'dept' + #deptId")
})
public void clearDeptResource(Long deptId) {
LogUtil.info("all permission resource of dept {} is cleanning...", deptId);
}
@Caching(evict = {
@CacheEvict(value = AuthConstants.ROLE_LINK_NAME, key = "'role' + #roleId"),
@CacheEvict(value = AuthConstants.ROLE_DATASET_NAME, key = "'role' + #roleId"),
@CacheEvict(value = AuthConstants.ROLE_PANEL_NAME, key = "'role' + #roleId")
})
public void clearRoleResource(Long roleId) {
LogUtil.info("all permission resource of role {} is cleanning...", roleId);
}
} }

View File

@ -1,6 +1,7 @@
package io.dataease.base.mapper.ext; package io.dataease.base.mapper.ext;
import io.dataease.auth.entity.AuthItem;
import io.dataease.base.domain.SysAuth; import io.dataease.base.domain.SysAuth;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -14,4 +15,16 @@ public interface ExtAuthMapper {
List<Long> queryUserIdWithDeptIds(@Param("deptIds") List<Long> deptIds); List<Long> queryUserIdWithDeptIds(@Param("deptIds") List<Long> deptIds);
List<SysAuth> queryByResource(@Param("resourceId") String resourceId); List<SysAuth> queryByResource(@Param("resourceId") String resourceId);
List<AuthItem> dataSourceIdByUser(String userId);
List<AuthItem> dataSetIdByUser(String userId);
List<AuthItem> panelIdByUser(String userId);
List<AuthItem> dataSourceIdByRole(String roleId);
List<AuthItem> dataSetIdByRole(String roleId);
List<AuthItem> panelIdByRole(String roleId);
List<AuthItem> dataSourceIdByDept(String deptId);
List<AuthItem> dataSetIdByDept(String deptId);
List<AuthItem> panelIdByDept(String deptId);
} }

View File

@ -2,6 +2,10 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="io.dataease.base.mapper.ext.ExtAuthMapper"> <mapper namespace="io.dataease.base.mapper.ext.ExtAuthMapper">
<resultMap id="AuthItemMap" type="io.dataease.auth.entity.AuthItem">
<result column="auth_source" property="authSource"/>
<result column="level" property="level"/>
</resultMap>
<select id="queryUserIdWithRoleIds" resultType="java.lang.Long" > <select id="queryUserIdWithRoleIds" resultType="java.lang.Long" >
select user_id select user_id
@ -29,6 +33,125 @@
where a.auth_source = #{resourceId} and b.privilege_value = 1 where a.auth_source = #{resourceId} and b.privilege_value = 1
</select> </select>
<select id="dataSourceIdByUser" resultMap="AuthItemMap">
SELECT
auth_source, MAX(d.privilege_type) as level
FROM
sys_auth a
LEFT JOIN sys_auth_detail d on d.auth_id = a.id
WHERE
auth_source_type = 'datasource'
AND auth_target_type = 'user'
AND auth_target = #{userId}
AND d.privilege_value = 1
GROUP BY a.id
</select>
<select id="dataSetIdByUser" resultMap="AuthItemMap" >
SELECT
auth_source, MAX(d.privilege_type) as level
FROM
sys_auth a
LEFT JOIN sys_auth_detail d on d.auth_id = a.id
WHERE
auth_source_type = 'dataset'
AND auth_target_type = 'user'
AND auth_target = #{userId}
AND d.privilege_value = 1
GROUP BY a.id
</select>
<select id="panelIdByUser" resultMap="AuthItemMap">
SELECT
auth_source, MAX(d.privilege_type) as level
FROM
sys_auth a
LEFT JOIN sys_auth_detail d on d.auth_id = a.id
WHERE
auth_source_type = 'panel'
AND auth_target_type = 'user'
AND auth_target = #{userId}
AND d.privilege_value = 1
GROUP BY a.id
</select>
<select id="dataSourceIdByRole" resultMap="AuthItemMap" >
SELECT
auth_source, MAX(d.privilege_type) as level
FROM
sys_auth a
LEFT JOIN sys_auth_detail d on d.auth_id = a.id
WHERE
auth_source_type = 'datasource'
AND auth_target_type = 'role'
AND auth_target = #{roleId}
AND d.privilege_value = 1
GROUP BY a.id
</select>
<select id="dataSetIdByRole" resultMap="AuthItemMap" >
SELECT
auth_source, MAX(d.privilege_type) as level
FROM
sys_auth a
LEFT JOIN sys_auth_detail d on d.auth_id = a.id
WHERE
auth_source_type = 'dataset'
AND auth_target_type = 'role'
AND auth_target = #{roleId}
AND d.privilege_value = 1
GROUP BY a.id
</select>
<select id="panelIdByRole" resultMap="AuthItemMap" >
SELECT
auth_source, MAX(d.privilege_type) as level
FROM
sys_auth a
LEFT JOIN sys_auth_detail d on d.auth_id = a.id
WHERE
auth_source_type = 'panel'
AND auth_target_type = 'role'
AND auth_target = #{roleId}
AND d.privilege_value = 1
GROUP BY a.id
</select>
<select id="dataSourceIdByDept" resultMap="AuthItemMap" >
SELECT
auth_source, MAX(d.privilege_type) as level
FROM
sys_auth a
LEFT JOIN sys_auth_detail d on d.auth_id = a.id
WHERE
auth_source_type = 'datasource'
AND auth_target_type = 'dept'
AND auth_target = #{deptId}
AND d.privilege_value = 1
GROUP BY a.id
</select>
<select id="dataSetIdByDept" resultMap="AuthItemMap" >
SELECT
auth_source, MAX(d.privilege_type) as level
FROM
sys_auth a
LEFT JOIN sys_auth_detail d on d.auth_id = a.id
WHERE
auth_source_type = 'dataset'
AND auth_target_type = 'dept'
AND auth_target = #{deptId}
AND d.privilege_value = 1
GROUP BY a.id
</select>
<select id="panelIdByDept" resultMap="AuthItemMap" >
SELECT
auth_source, MAX(d.privilege_type) as level
FROM
sys_auth a
LEFT JOIN sys_auth_detail d on d.auth_id = a.id
WHERE
auth_source_type = 'panel'
AND auth_target_type = 'dept'
AND auth_target = #{deptId}
AND d.privilege_value = 1
GROUP BY a.id
</select>
</mapper> </mapper>

View File

@ -9,4 +9,16 @@ public class AuthConstants {
public final static String ID_TOKEN_KEY = "IdToken"; public final static String ID_TOKEN_KEY = "IdToken";
public final static String USER_LINK_NAME = "user_link";
public final static String USER_DATASET_NAME = "user_dataset";
public final static String USER_PANEL_NAME = "user_panel";
public final static String ROLE_LINK_NAME = "role_link";
public final static String ROLE_DATASET_NAME = "role_dataset";
public final static String ROLE_PANEL_NAME = "role_panel";
public final static String DEPT_LINK_NAME = "dept_link";
public final static String DEPT_DATASET_NAME = "dept_dataset";
public final static String DEPT_PANEL_NAME = "dept_panel";
} }

View File

@ -0,0 +1,5 @@
package io.dataease.commons.constants;
public enum DePermissionType {
DATASOURCE, DATASET, PANEL
}

View File

@ -0,0 +1,35 @@
package io.dataease.commons.constants;
public enum ResourceAuthLevel {
COMMON_LEVEL_USE(1),
PANNEL_LEVEL_VIEW(1),
PANNEL_LEVEL_EXPORT(3),
PANNEL_LEVEL_MANAGE(5),
PANNEL_LEVEL_GRANT(15),
DATASET_LEVEL_USE(1),
DATASET_LEVEL_MANAGE(3),
DATASET_LEVEL_GRANT(15),
LINK_LEVEL_USE(1),
LINK_LEVEL_MANAGE(3),
LINK_LEVEL_GRANT(15);
private Integer level;
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
ResourceAuthLevel(Integer level) {
this.level = level;
}
}

View File

@ -0,0 +1,16 @@
package io.dataease.commons.model;
import lombok.Data;
import java.io.Serializable;
@Data
public class UserPermissionItem implements Serializable {
private String type;
private String resourceId;
}

View File

@ -1,18 +1,27 @@
package io.dataease.commons.utils; package io.dataease.commons.utils;
import io.dataease.auth.api.dto.CurrentRoleDto;
import io.dataease.auth.api.dto.CurrentUserDto; import io.dataease.auth.api.dto.CurrentUserDto;
import io.dataease.auth.entity.AuthItem;
import io.dataease.auth.service.ExtAuthService; import io.dataease.auth.service.ExtAuthService;
import io.dataease.commons.constants.ResourceAuthLevel;
import io.dataease.commons.model.AuthURD; import io.dataease.commons.model.AuthURD;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils; import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.util.Set; import java.util.*;
import java.util.stream.Collectors;
@Component @Component
public class AuthUtils { public class AuthUtils {
private static final String[] defaultPanelPermissions = {"panel_list"};
private static final String[] defaultDataSetPermissions = {"0"};
private static final String[] defaultLinkPermissions = {"0"};
private static ExtAuthService extAuthService; private static ExtAuthService extAuthService;
@Autowired @Autowired
@ -38,4 +47,53 @@ public class AuthUtils {
public static AuthURD authURDR(String resourceId) { public static AuthURD authURDR(String resourceId) {
return extAuthService.resourceTarget(resourceId); return extAuthService.resourceTarget(resourceId);
} }
public static Set<AuthItem> permissionByType(String type) {
CurrentUserDto user = getUser();
Long userId = user.getUserId();
Long deptId = user.getDeptId();
List<CurrentRoleDto> roles = user.getRoles();
Set<AuthItem> result = new HashSet<>();
if (StringUtils.equals("link", type)) {
Set<AuthItem> userSet = extAuthService.dataSourceIdByUser(userId).stream().collect(Collectors.toSet());
Set<AuthItem> roleSet = roles.stream().map(role -> extAuthService.dataSourceIdByRole(role.getId())).flatMap(Collection::stream).collect(Collectors.toSet());
Set<AuthItem> deptSet = extAuthService.dataSourceIdByDept(deptId).stream().collect(Collectors.toSet());
result.addAll(userSet);
result.addAll(roleSet);
result.addAll(deptSet);
Arrays.stream(defaultLinkPermissions).forEach(item -> {
result.add(new AuthItem(item, ResourceAuthLevel.LINK_LEVEL_MANAGE.getLevel()));
});
return result;
}
else if (StringUtils.equals("dataset", type)) {
Set<AuthItem> userSet = extAuthService.dataSetIdByUser(userId).stream().collect(Collectors.toSet());
Set<AuthItem> roleSet = roles.stream().map(role -> extAuthService.dataSetIdByRole(role.getId())).flatMap(Collection::stream).collect(Collectors.toSet());
Set<AuthItem> deptSet = extAuthService.dataSetIdByDept(deptId).stream().collect(Collectors.toSet());
result.addAll(userSet);
result.addAll(roleSet);
result.addAll(deptSet);
Arrays.stream(defaultDataSetPermissions).forEach(item -> {
result.add(new AuthItem(item, ResourceAuthLevel.DATASET_LEVEL_MANAGE.getLevel()));
});
return result;
}
else if (StringUtils.equals("panel", type)) {
Set<AuthItem> userSet = extAuthService.panelIdByUser(userId).stream().collect(Collectors.toSet());
Set<AuthItem> roleSet = roles.stream().map(role -> extAuthService.panelIdByRole(role.getId())).flatMap(Collection::stream).collect(Collectors.toSet());
Set<AuthItem> deptSet = extAuthService.panelIdByDept(deptId).stream().collect(Collectors.toSet());
result.addAll(userSet);
result.addAll(roleSet);
result.addAll(deptSet);
Arrays.stream(defaultPanelPermissions).forEach(item -> {
result.add(new AuthItem(item, ResourceAuthLevel.PANNEL_LEVEL_MANAGE.getLevel()));
});
return result;
}
return result;
}
} }

View File

@ -1,14 +1,19 @@
package io.dataease.controller.panel; package io.dataease.controller.panel;
import com.github.xiaoymin.knife4j.annotations.ApiSupport; import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.auth.annotation.DePermission;
import io.dataease.auth.annotation.DePermissions;
import io.dataease.base.domain.PanelGroup; import io.dataease.base.domain.PanelGroup;
import io.dataease.base.domain.PanelGroupWithBLOBs; import io.dataease.base.domain.PanelGroupWithBLOBs;
import io.dataease.commons.constants.DePermissionType;
import io.dataease.commons.constants.ResourceAuthLevel;
import io.dataease.controller.handler.annotation.I18n; import io.dataease.controller.handler.annotation.I18n;
import io.dataease.controller.request.panel.PanelGroupRequest; import io.dataease.controller.request.panel.PanelGroupRequest;
import io.dataease.dto.panel.PanelGroupDTO; import io.dataease.dto.panel.PanelGroupDTO;
import io.dataease.service.panel.PanelGroupService; import io.dataease.service.panel.PanelGroupService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.Logical;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -42,18 +47,24 @@ public class PanelGroupController {
@ApiOperation("保存") @ApiOperation("保存")
@PostMapping("/save") @PostMapping("/save")
@DePermissions(value = {
@DePermission(type = DePermissionType.PANEL, value = "id"),
@DePermission(type = DePermissionType.PANEL, value = "pid", level = ResourceAuthLevel.PANNEL_LEVEL_MANAGE)
}, logical = Logical.AND)
@I18n @I18n
public PanelGroup saveOrUpdate(@RequestBody PanelGroupRequest request) { public PanelGroup saveOrUpdate(@RequestBody PanelGroupRequest request) {
return panelGroupService.saveOrUpdate(request); return panelGroupService.saveOrUpdate(request);
} }
@ApiOperation("删除") @ApiOperation("删除")
@DePermission(type = DePermissionType.PANEL, level = ResourceAuthLevel.PANNEL_LEVEL_MANAGE)
@PostMapping("/deleteCircle/{id}") @PostMapping("/deleteCircle/{id}")
public void deleteCircle(@PathVariable String id) { public void deleteCircle(@PathVariable String id) {
panelGroupService.deleteCircle(id); panelGroupService.deleteCircle(id);
} }
@ApiOperation("详细信息") @ApiOperation("详细信息")
@DePermission(type = DePermissionType.PANEL, level = ResourceAuthLevel.PANNEL_LEVEL_VIEW)
@GetMapping("/findOne/{id}") @GetMapping("/findOne/{id}")
public PanelGroupWithBLOBs findOne(@PathVariable String id) throws Exception { public PanelGroupWithBLOBs findOne(@PathVariable String id) throws Exception {
return panelGroupService.findOne(id); return panelGroupService.findOne(id);

View File

@ -23,6 +23,8 @@ import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore; import springfox.documentation.annotations.ApiIgnore;
@ -44,6 +46,7 @@ public class SysUserController {
private SysRoleService sysRoleService; private SysRoleService sysRoleService;
@ApiOperation("查询用户") @ApiOperation("查询用户")
@RequiresPermissions("user:read")
@PostMapping("/userGrid/{goPage}/{pageSize}") @PostMapping("/userGrid/{goPage}/{pageSize}")
@ApiImplicitParams({ @ApiImplicitParams({
@ApiImplicitParam(paramType="path", name = "goPage", value = "页码", required = true, dataType = "Integer"), @ApiImplicitParam(paramType="path", name = "goPage", value = "页码", required = true, dataType = "Integer"),
@ -57,18 +60,21 @@ public class SysUserController {
@ApiOperation("创建用户") @ApiOperation("创建用户")
@RequiresPermissions("user:add")
@PostMapping("/create") @PostMapping("/create")
public void create(@RequestBody SysUserCreateRequest request){ public void create(@RequestBody SysUserCreateRequest request){
sysUserService.save(request); sysUserService.save(request);
} }
@ApiOperation("更新用户") @ApiOperation("更新用户")
@RequiresPermissions("user:edit")
@PostMapping("/update") @PostMapping("/update")
public void update(@RequestBody SysUserCreateRequest request){ public void update(@RequestBody SysUserCreateRequest request){
sysUserService.update(request); sysUserService.update(request);
} }
@ApiOperation("删除用户") @ApiOperation("删除用户")
@RequiresPermissions("user:del")
@PostMapping("/delete/{userId}") @PostMapping("/delete/{userId}")
@ApiImplicitParam(paramType = "path", value = "用户ID", name = "userId", required = true, dataType = "Integer") @ApiImplicitParam(paramType = "path", value = "用户ID", name = "userId", required = true, dataType = "Integer")
public void delete(@PathVariable("userId") Long userId){ public void delete(@PathVariable("userId") Long userId){
@ -77,6 +83,8 @@ public class SysUserController {
@ApiOperation("更新用户状态") @ApiOperation("更新用户状态")
@RequiresPermissions("user:edit")
@RequiresRoles("1")
@PostMapping("/updateStatus") @PostMapping("/updateStatus")
public void updateStatus(@RequestBody SysUserStateRequest request){ public void updateStatus(@RequestBody SysUserStateRequest request){
sysUserService.updateStatus(request); sysUserService.updateStatus(request);
@ -89,6 +97,7 @@ public class SysUserController {
sysUserService.updatePwd(request); sysUserService.updatePwd(request);
} }
@ApiOperation("更新指定用户密码") @ApiOperation("更新指定用户密码")
@RequiresPermissions("user:editPwd")
@PostMapping("/adminUpdatePwd") @PostMapping("/adminUpdatePwd")
public void adminUpdatePwd(@RequestBody SysUserPwdRequest request){ public void adminUpdatePwd(@RequestBody SysUserPwdRequest request){
sysUserService.adminUpdatePwd(request); sysUserService.adminUpdatePwd(request);

View File

@ -12,17 +12,19 @@ import io.dataease.plugins.xpack.auth.dto.request.XpackSysAuthRequest;
import io.dataease.plugins.xpack.auth.dto.response.XpackSysAuthDetail; import io.dataease.plugins.xpack.auth.dto.response.XpackSysAuthDetail;
import io.dataease.plugins.xpack.auth.dto.response.XpackSysAuthDetailDTO; import io.dataease.plugins.xpack.auth.dto.response.XpackSysAuthDetailDTO;
import io.dataease.plugins.xpack.auth.dto.response.XpackVAuthModelDTO; import io.dataease.plugins.xpack.auth.dto.response.XpackVAuthModelDTO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import io.dataease.plugins.xpack.auth.service.AuthXpackService; import io.dataease.plugins.xpack.auth.service.AuthXpackService;
import java.util.List;
import java.util.Map; import java.util.*;
import java.util.Optional;
@RequestMapping("/plugin/auth") @RequestMapping("/plugin/auth")
@RestController @RestController
public class XAuthServer { public class XAuthServer {
private static final Set<String> cacheTypes = new HashSet<>();
@PostMapping("/authModels") @PostMapping("/authModels")
@I18n @I18n
public List<XpackVAuthModelDTO> authModels(@RequestBody XpackBaseTreeRequest request){ public List<XpackVAuthModelDTO> authModels(@RequestBody XpackBaseTreeRequest request){
@ -64,6 +66,26 @@ public class XAuthServer {
CacheUtils.removeAll(AuthConstants.USER_ROLE_CACHE_NAME); CacheUtils.removeAll(AuthConstants.USER_ROLE_CACHE_NAME);
CacheUtils.removeAll(AuthConstants.USER_PERMISSION_CACHE_NAME); CacheUtils.removeAll(AuthConstants.USER_PERMISSION_CACHE_NAME);
} }
String authCacheKey = getAuthCacheKey(request);
if (StringUtils.isNotBlank(authCacheKey)) {
CacheUtils.remove(authCacheKey, request.getAuthTargetType() + request.getAuthTarget());
}
}); });
} }
private String getAuthCacheKey(XpackSysAuthRequest request) {
if (CollectionUtils.isEmpty(cacheTypes)) {
cacheTypes.add("link");
cacheTypes.add("dataset");
cacheTypes.add("panel");
}
String authTargetType = request.getAuthTargetType();
String authSourceType = request.getAuthSourceType();
if (!cacheTypes.contains(authSourceType)) {
return null;
}
return authTargetType + "_" + authSourceType;
}
} }

View File

@ -1,6 +1,7 @@
package io.dataease.plugins.server; package io.dataease.plugins.server;
import io.dataease.auth.service.ExtAuthService;
import io.dataease.commons.utils.BeanUtils; import io.dataease.commons.utils.BeanUtils;
import io.dataease.controller.sys.response.DeptNodeResponse; import io.dataease.controller.sys.response.DeptNodeResponse;
import io.dataease.plugins.common.entity.XpackGridRequest; import io.dataease.plugins.common.entity.XpackGridRequest;
@ -13,6 +14,7 @@ import io.dataease.plugins.xpack.dept.dto.response.XpackSysDept;
import io.dataease.plugins.xpack.dept.service.DeptXpackService; import io.dataease.plugins.xpack.dept.service.DeptXpackService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore; import springfox.documentation.annotations.ApiIgnore;
@ -23,6 +25,9 @@ import java.util.stream.Collectors;
@RestController @RestController
public class XDeptServer { public class XDeptServer {
@Autowired
private ExtAuthService extAuthService;
@ApiOperation("查询子节点") @ApiOperation("查询子节点")
@PostMapping("/childNodes/{pid}") @PostMapping("/childNodes/{pid}")
public List<DeptNodeResponse> childNodes(@PathVariable("pid") Long pid){ public List<DeptNodeResponse> childNodes(@PathVariable("pid") Long pid){
@ -72,6 +77,9 @@ public class XDeptServer {
@PostMapping("/delete") @PostMapping("/delete")
public void delete(@RequestBody List<XpackDeleteDept> requests){ public void delete(@RequestBody List<XpackDeleteDept> requests){
DeptXpackService deptService = SpringContextUtil.getBean(DeptXpackService.class); DeptXpackService deptService = SpringContextUtil.getBean(DeptXpackService.class);
requests.forEach(request -> {
extAuthService.clearDeptResource(request.getDeptId());
});
deptService.batchDelete(requests); deptService.batchDelete(requests);
} }

View File

@ -3,6 +3,7 @@ package io.dataease.plugins.server;
import com.github.pagehelper.Page; import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import io.dataease.auth.service.ExtAuthService;
import io.dataease.commons.utils.PageUtils; import io.dataease.commons.utils.PageUtils;
import io.dataease.commons.utils.Pager; import io.dataease.commons.utils.Pager;
import io.dataease.plugins.common.entity.XpackGridRequest; import io.dataease.plugins.common.entity.XpackGridRequest;
@ -12,6 +13,7 @@ import io.dataease.plugins.xpack.role.dto.response.XpackRoleItemDto;
import io.dataease.plugins.xpack.role.service.RoleXpackService; import io.dataease.plugins.xpack.role.service.RoleXpackService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore; import springfox.documentation.annotations.ApiIgnore;
@ -21,6 +23,8 @@ import java.util.List;
@RestController @RestController
public class XRoleServer { public class XRoleServer {
@Autowired
private ExtAuthService extAuthService;
@ApiOperation("新增角色") @ApiOperation("新增角色")
@PostMapping("/create") @PostMapping("/create")
@ -34,6 +38,7 @@ public class XRoleServer {
@PostMapping("/delete/{roleId}") @PostMapping("/delete/{roleId}")
public void delete(@PathVariable("roleId") Long roleId){ public void delete(@PathVariable("roleId") Long roleId){
RoleXpackService roleXpackService = SpringContextUtil.getBean(RoleXpackService.class); RoleXpackService roleXpackService = SpringContextUtil.getBean(RoleXpackService.class);
extAuthService.clearDeptResource(roleId);
roleXpackService.delete(roleId); roleXpackService.delete(roleId);
} }

View File

@ -1,6 +1,7 @@
package io.dataease.service.sys; package io.dataease.service.sys;
import io.dataease.auth.api.dto.CurrentUserDto; import io.dataease.auth.api.dto.CurrentUserDto;
import io.dataease.auth.service.ExtAuthService;
import io.dataease.base.domain.SysUser; import io.dataease.base.domain.SysUser;
import io.dataease.base.domain.SysUserExample; import io.dataease.base.domain.SysUserExample;
import io.dataease.base.domain.SysUsersRolesExample; import io.dataease.base.domain.SysUsersRolesExample;
@ -27,6 +28,7 @@ import io.dataease.plugins.xpack.oidc.dto.SSOUserInfo;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -54,6 +56,9 @@ public class SysUserService {
@Resource @Resource
private ExtSysUserMapper extSysUserMapper; private ExtSysUserMapper extSysUserMapper;
@Autowired
private ExtAuthService extAuthService;
public List<SysUserGridResponse> query(BaseGridRequest request) { public List<SysUserGridResponse> query(BaseGridRequest request) {
@ -268,6 +273,7 @@ public class SysUserService {
@CacheEvict(value = AuthConstants.USER_CACHE_NAME, key = "'user' + #userId") @CacheEvict(value = AuthConstants.USER_CACHE_NAME, key = "'user' + #userId")
@Transactional @Transactional
public int delete(Long userId) { public int delete(Long userId) {
extAuthService.clearUserResource(userId);
deleteUserRoles(userId); deleteUserRoles(userId);
return sysUserMapper.deleteByPrimaryKey(userId); return sysUserMapper.deleteByPrimaryKey(userId);
} }

View File

@ -79,7 +79,7 @@
timeToLiveSeconds="60" timeToLiveSeconds="60"
memoryStoreEvictionPolicy="FIFO" memoryStoreEvictionPolicy="FIFO"
> >
<cacheEventListenerFactory class="io.dataease.listener.LicCacheEventListener" /> <cacheEventListenerFactory class="io.dataease.listener.LicCacheEventListener"/>
</cache> </cache>
<cache <cache
@ -97,45 +97,157 @@
<!--消息渠道缓存--> <!--消息渠道缓存-->
<cache <cache
name="sys_msg_channel" name="sys_msg_channel"
eternal="true" eternal="true"
maxElementsInMemory="100" maxElementsInMemory="100"
maxElementsOnDisk="1000" maxElementsOnDisk="1000"
overflowToDisk="true" overflowToDisk="true"
diskPersistent="false" diskPersistent="false"
/> />
<!--消息类型缓存--> <!--消息类型缓存-->
<cache <cache
name="sys_msg_type" name="sys_msg_type"
eternal="true" eternal="true"
maxElementsInMemory="100" maxElementsInMemory="100"
maxElementsOnDisk="1000" maxElementsOnDisk="1000"
overflowToDisk="true" overflowToDisk="true"
diskPersistent="false" diskPersistent="false"
/> />
<!--消息类型缓存--> <!--消息类型缓存-->
<cache <cache
name="sys_msg_user_subscribe" name="sys_msg_user_subscribe"
eternal="false" eternal="false"
maxElementsInMemory="100" maxElementsInMemory="100"
maxElementsOnDisk="10000" maxElementsOnDisk="10000"
overflowToDisk="true" overflowToDisk="true"
diskPersistent="false" diskPersistent="false"
timeToIdleSeconds="28800" timeToIdleSeconds="28800"
timeToLiveSeconds="86400" timeToLiveSeconds="86400"
memoryStoreEvictionPolicy="LRU" memoryStoreEvictionPolicy="LRU"
/> />
<!--消息类型缓存--> <!--消息类型缓存-->
<cache <cache
name="sys_map_areas" name="sys_map_areas"
eternal="true" eternal="true"
maxElementsInMemory="100" maxElementsInMemory="100"
maxElementsOnDisk="3000" maxElementsOnDisk="3000"
overflowToDisk="true" overflowToDisk="true"
diskPersistent="false" diskPersistent="false"
/>
<!--用户授权数据源缓存-->
<cache
name="user_link"
eternal="false"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/>
<!--用户授权数据集缓存-->
<cache
name="user_dataset"
eternal="false"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/>
<!--用户授权仪表板缓存-->
<cache
name="user_panel"
eternal="false"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/>
<!--角色授权数据源缓存-->
<cache
name="role_link"
eternal="false"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/>
<!--角色授权数据集缓存-->
<cache
name="role_dataset"
eternal="false"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/>
<!--角色授权仪表板缓存-->
<cache
name="role_panel"
eternal="false"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/>
<!--组织授权数据源缓存-->
<cache
name="dept_link"
eternal="false"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/>
<!--组织授权数据集缓存-->
<cache
name="dept_dataset"
eternal="false"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/>
<!--组织授权仪表板缓存-->
<cache
name="dept_panel"
eternal="false"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/> />