@PostConstruct 用于启动时对项目权限进行扫描
/**
* @author 梁宏平
* @date 2022.09.05
**/
public class ShiroPermissionConstant {
public static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
/**
* 配置需要扫描权限的包 多个 就配置多个
*/
public static final String[] basePackages={"com.test.tedt"};
}
import com.sixeco.framework.common.api.ApiDoc;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.ConfigurablePropertyResolver;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySourcesPropertyResolver;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.*;
@RestController
@RequiresPermissions("parent")
@ApiDoc("test")
@RequestMapping("/security")
public class SyncPermissionController {
private static final MutablePropertySources propertySources = new MutablePropertySources();
private static final ConfigurablePropertyResolver propertyResolver =
new PropertySourcesPropertyResolver(propertySources);
private static final PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
private static final ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
@Autowired
private AdminPermissionEntityIService adminPermissionEntityIService;
@GetMapping("/reScanPermission")
public Result reScanPermission() {
try {
flushPermissionToDbAtStartup();
return Result.success("");
} catch (IOException e) {
e.printStackTrace();
return Result.error("刷新权限失败");
}
}
@PostConstruct
public void flushPermissionToDbAtStartup() throws IOException {
List<AdminPermissionEntity> permissionList = scanPermissions();
List<AdminPermissionEntity> adminPermissionEntityList = adminPermissionEntityIService.list();
Map<String, AdminPermissionEntity> permissionCodeAndEntityMap = new HashMap<>();
for (AdminPermissionEntity tempAdminPermissionEntity : permissionList) {
permissionCodeAndEntityMap.put(tempAdminPermissionEntity.getCode(), tempAdminPermissionEntity);
}
for (AdminPermissionEntity tempAdminPermissionEntity : adminPermissionEntityList) {
if (permissionCodeAndEntityMap.containsKey(tempAdminPermissionEntity.getCode())) {
tempAdminPermissionEntity.setPath(permissionCodeAndEntityMap.get(tempAdminPermissionEntity.getCode()).getPath());
tempAdminPermissionEntity.setName(permissionCodeAndEntityMap.get(tempAdminPermissionEntity.getCode()).getName());
permissionCodeAndEntityMap.remove(tempAdminPermissionEntity.getCode());
}
}
if (CollectionUtils.isNotEmpty(permissionCodeAndEntityMap.values())) {
adminPermissionEntityIService.saveBatch(permissionCodeAndEntityMap.values());
}
if(CollectionUtils.isNotEmpty(adminPermissionEntityList)){
adminPermissionEntityIService.updateBatchById(adminPermissionEntityList);
}
}
private List<AdminPermissionEntity> scanPermissions() throws IOException {
String[] packageSearchPath = converBasePackageToSearchPath(ShiroPermissionConstant.basePackages);
List<Resource> resourceList = new ArrayList<>();
Resource[] resources = null;
if (packageSearchPath != null) {
for (String packageSearch : packageSearchPath) {
resources = pathMatchingResourcePatternResolver.getResources(packageSearch);
}
if (ArrayUtils.isNotEmpty(resources)) {
resourceList.addAll(Arrays.asList(resources));
}
}
List<AdminPermissionEntity> parentAdminPermissionEntityList = null;
List<AdminPermissionEntity> childAdminPermissionEntityList = null;
List<AdminPermissionEntity> result = new ArrayList<>();
Map<AdminPermissionEntity, List<AdminPermissionEntity>> tempMap = null;
for (Resource resource : resourceList) {
MetadataReader metadataReader = new CachingMetadataReaderFactory().getMetadataReader(resource);
if (metadataReader.getAnnotationMetadata().hasAnnotatedMethods(RequiresPermissions.class.getName()) || metadataReader.getAnnotationMetadata().hasAnnotation(RequiresPermissions.class.getName())) {
Class clazz = null;
try {
clazz = classLoader.loadClass(metadataReader.getClassMetadata().getClassName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (clazz != null) {
if (metadataReader.getAnnotationMetadata().hasAnnotation(RequiresPermissions.class.getName())) {
parentAdminPermissionEntityList = extractClassMetaPermission(clazz);
if (CollectionUtils.isNotEmpty(parentAdminPermissionEntityList)) {
result.addAll(parentAdminPermissionEntityList);
}
}
if (metadataReader.getAnnotationMetadata().hasAnnotatedMethods(RequiresPermissions.class.getName())) {
childAdminPermissionEntityList = extractClassMethodPermissions(clazz);
if (CollectionUtils.isNotEmpty(childAdminPermissionEntityList)) {
result.addAll(childAdminPermissionEntityList);
}
}
}
}
}
return result;
}
private List<AdminPermissionEntity> extractClassMetaPermission(Class clazz) {
ApiDoc apiDoc = AnnotationUtils.findAnnotation(clazz, ApiDoc.class);
AdminPermissionEntity adminPermissionEntity;
RequiresPermissions requiresPermissions = AnnotationUtils.findAnnotation(clazz, RequiresPermissions.class);
List<AdminPermissionEntity> adminPermissionEntityList = new ArrayList<>();
if (requiresPermissions != null && ArrayUtils.isNotEmpty(requiresPermissions.value())) {
for (String code : requiresPermissions.value()) {
adminPermissionEntity = new AdminPermissionEntity();
if (apiDoc != null) {
if (StringUtils.isNotEmpty(apiDoc.value())) {
adminPermissionEntity.setName(apiDoc.value());
} else {
adminPermissionEntity.setName(apiDoc.groupDesc());
}
}
adminPermissionEntity.setPath(extractRequestPath(clazz, null));
adminPermissionEntity.setCode(code);
adminPermissionEntity.setStatus(0);
adminPermissionEntityList.add(adminPermissionEntity);
}
}
return adminPermissionEntityList;
}
private List<AdminPermissionEntity> extractClassMethodPermissions(Class clazz) {
Method[] methodsArr = ReflectionUtils.getAllDeclaredMethods(clazz);
List<AdminPermissionEntity> adminPermissionEntityList = new ArrayList<>();
ApiDoc apiDoc;
RequiresPermissions requiresPermissions;
AdminPermissionEntity adminPermissionEntity;
if (ArrayUtils.isNotEmpty(methodsArr)) {
for (Method method : methodsArr) {
apiDoc = AnnotationUtils.findAnnotation(method, ApiDoc.class);
requiresPermissions = AnnotationUtils.findAnnotation(method, RequiresPermissions.class);
if (requiresPermissions != null && ArrayUtils.isNotEmpty(requiresPermissions.value())) {
for (String code : requiresPermissions.value()) {
adminPermissionEntity = new AdminPermissionEntity();
adminPermissionEntity.setStatus(0);
if (apiDoc != null) {
adminPermissionEntity.setName(apiDoc.groupDesc());
}
adminPermissionEntity.setPath(extractRequestPath(clazz, method));
adminPermissionEntity.setCode(code);
adminPermissionEntityList.add(adminPermissionEntity);
}
}
}
}
return adminPermissionEntityList;
}
private String extractRequestPath(Class clazz, Method method) {
RequestMapping requestMapping;
PostMapping postMapping;
PatchMapping patchMapping;
GetMapping getMapping;
DeleteMapping deleteMapping;
PutMapping putMapping;
String path = "";
if (clazz != null && method != null) {
path = extractRequestPath(clazz, null);
path += extractRequestPath(null, method);
} else if (clazz != null) {
requestMapping = AnnotationUtils.findAnnotation(clazz, RequestMapping.class);
path = requestMapping != null ? (StringUtils.isNotEmpty(requestMapping.name()) ? requestMapping.name() : (ArrayUtils.isNotEmpty(requestMapping.value()) ? requestMapping.value()[0] : "")) : "";
if (StringUtils.isEmpty(path)) {
postMapping = AnnotationUtils.findAnnotation(clazz, PostMapping.class);
path = postMapping != null ? (StringUtils.isNotEmpty(postMapping.name()) ? postMapping.name() : (ArrayUtils.isNotEmpty(postMapping.value()) ? postMapping.value()[0] : "")) : "";
if (StringUtils.isEmpty(path)) {
getMapping = AnnotationUtils.findAnnotation(clazz, GetMapping.class);
path = getMapping != null ? (StringUtils.isNotEmpty(getMapping.name()) ? getMapping.name() : (ArrayUtils.isNotEmpty(getMapping.value()) ? getMapping.value()[0] : "")) : "";
if (StringUtils.isEmpty(path)) {
patchMapping = AnnotationUtils.findAnnotation(clazz, PatchMapping.class);
path = patchMapping != null ? (StringUtils.isNotEmpty(patchMapping.name()) ? patchMapping.name() : (ArrayUtils.isNotEmpty(patchMapping.value()) ? patchMapping.value()[0] : "")) : "";
if (StringUtils.isEmpty(path)) {
deleteMapping = AnnotationUtils.findAnnotation(clazz, DeleteMapping.class);
path = deleteMapping != null ? (StringUtils.isNotEmpty(deleteMapping.name()) ? deleteMapping.name() : (ArrayUtils.isNotEmpty(deleteMapping.value()) ? deleteMapping.value()[0] : "")) : "";
if (StringUtils.isEmpty(path)) {
putMapping = AnnotationUtils.findAnnotation(clazz, PutMapping.class);
path = putMapping != null ? (StringUtils.isNotEmpty(putMapping.name()) ? putMapping.name() : (ArrayUtils.isNotEmpty(putMapping.value()) ? putMapping.value()[0] : "")) : "";
}
}
}
}
}
} else if (method != null) {
requestMapping = AnnotationUtils.findAnnotation(method, RequestMapping.class);
path = requestMapping != null ? (StringUtils.isNotEmpty(requestMapping.name()) ? requestMapping.name() : (ArrayUtils.isNotEmpty(requestMapping.value()) ? requestMapping.value()[0] : "")) : "";
if (StringUtils.isEmpty(path)) {
postMapping = AnnotationUtils.findAnnotation(method, PostMapping.class);
path = postMapping != null ? (StringUtils.isNotEmpty(postMapping.name()) ? postMapping.name() : (ArrayUtils.isNotEmpty(postMapping.value()) ? postMapping.value()[0] : "")) : "";
if (StringUtils.isEmpty(path)) {
getMapping = AnnotationUtils.findAnnotation(method, GetMapping.class);
path = getMapping != null ? (StringUtils.isNotEmpty(getMapping.name()) ? getMapping.name() : (ArrayUtils.isNotEmpty(getMapping.value()) ? getMapping.value()[0] : "")) : "";
if (StringUtils.isEmpty(path)) {
patchMapping = AnnotationUtils.findAnnotation(method, PatchMapping.class);
path = patchMapping != null ? (StringUtils.isNotEmpty(patchMapping.name()) ? patchMapping.name() : (ArrayUtils.isNotEmpty(patchMapping.value()) ? patchMapping.value()[0] : "")) : "";
if (StringUtils.isEmpty(path)) {
deleteMapping = AnnotationUtils.findAnnotation(method, DeleteMapping.class);
path = deleteMapping != null ? (StringUtils.isNotEmpty(deleteMapping.name()) ? deleteMapping.name() : (ArrayUtils.isNotEmpty(deleteMapping.value()) ? deleteMapping.value()[0] : "")) : "";
if (StringUtils.isEmpty(path)) {
putMapping = AnnotationUtils.findAnnotation(method, PutMapping.class);
path = putMapping != null ? (StringUtils.isNotEmpty(putMapping.name()) ? putMapping.name() : (ArrayUtils.isNotEmpty(putMapping.value()) ? putMapping.value()[0] : "")) : "";
}
}
}
}
}
}
return path;
}
private String[] converBasePackageToSearchPath(String[] basePackages) {
if (ArrayUtils.isEmpty(basePackages)) {
return null;
}
return Arrays.stream(basePackages).map(basePackage -> ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + ShiroPermissionConstant.DEFAULT_RESOURCE_PATTERN).toArray(String[]::new);
}
private String resolveBasePackage(String basePackage) {
return ClassUtils.convertClassNameToResourcePath(propertyResolver.resolveRequiredPlaceholders(basePackage));
}
}