From a5d5787735605f2c89b1ed7671178bf05ed06d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A9=E5=A4=A9=E5=90=91=E4=B8=8A?= Date: Wed, 30 Nov 2022 08:40:31 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9'{'=E5=AF=B9=E9=BD=90=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/PathPermissionMappingConfig.java | 47 ++++++++++++------- .../com/ruoyi/gateway/filter/AuthFilter.java | 36 +++++++++----- 2 files changed, 54 insertions(+), 29 deletions(-) diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/PathPermissionMappingConfig.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/PathPermissionMappingConfig.java index 7afd7523..afee49ae 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/PathPermissionMappingConfig.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/PathPermissionMappingConfig.java @@ -19,16 +19,17 @@ import java.util.*; /** * =====================================网关鉴权使用说明======================================= * 场景: - * 微服务部署在内网,确定安全,无需在每个微服务都实现鉴权的逻辑,可以在网关层面实现统一鉴权 + * 微服务部署在内网,确定安全,无需在每个微服务都实现鉴权的逻辑,可以在网关层面实现统一鉴权 * 使用方式: - * 1、在每个微服务的配置文件中添加参数:security.annotation.enabled: false 关闭系统默认的通过注解方式鉴权,默认开启 - * 2、在每个微服务的配置文件中添加参数:pathPrefix: 值为网关中微服务匹配的路由地址前缀,例如: /auth - * 3、在网关配置文件中添加参数:security.gateway.enabled: true 启用网关统一鉴权,默认关闭 - * + * 1、在每个微服务的配置文件中添加参数:security.annotation.enabled: false 关闭系统默认的通过注解方式鉴权,默认开启 + * 2、在每个微服务的配置文件中添加参数:pathPrefix: 值为网关中微服务匹配的路由地址前缀,例如: /auth + * 3、在网关配置文件中添加参数:security.gateway.enabled: true 启用网关统一鉴权,默认关闭 + *

* 通过反射扫描所有控制器,缓存所有控制器的映射路径以及对应的权限注解,缓存到redis,方便网关鉴权 */ @ConditionalOnProperty(prefix = "security.annotation", name = "enabled", havingValue = "false") -public class PathPermissionMappingConfig { +public class PathPermissionMappingConfig +{ /** * 微服务在网关配置中predicates中的Path前缀,例如: /system */ @@ -36,7 +37,8 @@ public class PathPermissionMappingConfig { private String pathPrefix; @PostConstruct - public PathPermissionMappingConfig execute() { + public PathPermissionMappingConfig execute() + { RedisService redisService = SpringUtils.getBean(RedisService.class); RequestMappingHandlerMapping bean = SpringUtils.getBean("requestMappingHandlerMapping"); Map handlerMethods = bean.getHandlerMethods(); @@ -45,7 +47,8 @@ public class PathPermissionMappingConfig { */ Map pathPermsMap = new TreeMap<>(); - handlerMethods.forEach((k, v) -> { + handlerMethods.forEach((k, v) -> + { RequiresRoles requiresRoles = v.getMethodAnnotation(RequiresRoles.class); RequiresPermissions requiresPermissions = v.getMethodAnnotation(RequiresPermissions.class); @@ -54,21 +57,27 @@ public class PathPermissionMappingConfig { /** * @RequestMapping注解 */ - if(methods.isEmpty()) { + if (methods.isEmpty()) + { methods = new HashSet<>(); methods.addAll(Arrays.asList(RequestMethod.GET, RequestMethod.POST)); } - if(requiresPermissions == null && requiresRoles == null) { + if (requiresPermissions == null && requiresRoles == null) + { addPathPermsMap(SecurityConstants.ROLE_ANON, pathPermsMap, methods, patternValues); } - if(requiresPermissions != null) { - for (String perms : requiresPermissions.value()) { + if (requiresPermissions != null) + { + for (String perms : requiresPermissions.value()) + { addPathPermsMap(perms, pathPermsMap, methods, patternValues); } } - if(requiresRoles != null) { - for (String role : requiresRoles.value()) { + if (requiresRoles != null) + { + for (String role : requiresRoles.value()) + { addPathPermsMap(SecurityConstants.ROLE_PREFIX + role, pathPermsMap, methods, patternValues); } } @@ -80,14 +89,18 @@ public class PathPermissionMappingConfig { /** * 一个path对应多个perms + * * @param perms * @param pathPermsMap * @param methods * @param patternValues */ - private void addPathPermsMap(String perms, Map pathPermsMap, Set methods, Set patternValues) { - for (RequestMethod method : methods) { - for (String patternValue : patternValues) { + private void addPathPermsMap(String perms, Map pathPermsMap, Set methods, Set patternValues) + { + for (RequestMethod method : methods) + { + for (String patternValue : patternValues) + { String key = pathPrefix + patternValue + "_" + method.name(); pathPermsMap.put(key, perms); } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java index d2540622..01e534c5 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java @@ -31,7 +31,7 @@ import java.util.stream.Collectors; /** * 网关鉴权 - * + * * @author ruoyi */ @Component @@ -92,14 +92,17 @@ public class AuthFilter implements GlobalFilter, Ordered // 内部请求来源参数清除 removeHeader(mutate, SecurityConstants.FROM_SOURCE); // 通过网关鉴权 - if(gatewayAuth) { + if (gatewayAuth) + { // admin不需要鉴权 - if(isAdmin(userid)) { + if (isAdmin(userid)) + { return chain.filter(exchange.mutate().request(mutate.build()).build()); } // 网关验证权限 String api = url + "_" + request.getMethod().name(); - if(!hasPermission(api, userkey)) { + if (!hasPermission(api, userkey)) + { log.warn("无权访问:{}", api); return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "无权访问", HttpStatus.FORBIDDEN); } @@ -107,11 +110,13 @@ public class AuthFilter implements GlobalFilter, Ordered return chain.filter(exchange.mutate().request(mutate.build()).build()); } - private boolean isAdmin(String userid) { + private boolean isAdmin(String userid) + { return "1".equals(userid); } - private boolean hasPermission(String api, String token) { + private boolean hasPermission(String api, String token) + { // 使用JSONObject接收,避免导入依赖 JSONObject loginUser = redisService.getCacheObject(CacheConstants.LOGIN_TOKEN_KEY + token); // 获取登录用户的资源列表 @@ -125,28 +130,33 @@ public class AuthFilter implements GlobalFilter, Ordered .filter(entry -> match(entry.getKey(), api)) .map(entry -> entry.getValue()) .collect(Collectors.toSet()); - if(!matchedPerms.isEmpty()) { + if (!matchedPerms.isEmpty()) + { // 所有角色权限 Set rolePerms = matchedPerms.stream().filter(item -> item.startsWith("ROLE_")).collect(Collectors.toSet()); // 所有资源权限 matchedPerms.removeAll(rolePerms); - if(!rolePerms.isEmpty()) { - if(rolePerms.contains(SecurityConstants.ROLE_ANON)) { + if (!rolePerms.isEmpty()) + { + if (rolePerms.contains(SecurityConstants.ROLE_ANON)) + { log.debug("允许访问公共权限:{},{}", api, rolePerms); return true; } rolePerms = rolePerms.stream().map(item -> item.substring(SecurityConstants.ROLE_PREFIX.length())).collect(Collectors.toSet()); // 求交集 rolePerms.retainAll(roles); - if(!rolePerms.isEmpty()) { + if (!rolePerms.isEmpty()) + { log.debug("允许访问角色权限:{}, {}", api, rolePerms); return true; } } // 求交集 matchedPerms.retainAll(permissions); - if(!matchedPerms.isEmpty()) { + if (!matchedPerms.isEmpty()) + { log.debug("允许访问资源权限:{},{}", api, matchedPerms); return true; } @@ -155,9 +165,11 @@ public class AuthFilter implements GlobalFilter, Ordered return false; } - private boolean match(String pattern, String api) { + private boolean match(String pattern, String api) + { return antPathMatcher.match(pattern, api); } + private void addHeader(ServerHttpRequest.Builder mutate, String name, Object value) { if (value == null)