diff --git a/spring-boot-demo-rbac-security/README.md b/spring-boot-demo-rbac-security/README.md index 5eab089..611a0bc 100644 --- a/spring-boot-demo-rbac-security/README.md +++ b/spring-boot-demo-rbac-security/README.md @@ -388,7 +388,10 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { ### 3.4. RbacAuthorityService.java -> 路由动态鉴权类,主要功能:根据当前请求路径与该用户可访问的资源做匹配,通过则可以访问,否则,不允许访问 +> 路由动态鉴权类,主要功能: +> +> 1. 校验请求的合法性,排除404和405这两种异常请求 +> 2. 根据当前请求路径与该用户可访问的资源做匹配,通过则可以访问,否则,不允许访问 ```java /** @@ -412,7 +415,12 @@ public class RbacAuthorityService { @Autowired private PermissionDao permissionDao; + @Autowired + private RequestMappingHandlerMapping mapping; + public boolean hasPermission(HttpServletRequest request, Authentication authentication) { + checkRequest(request); + Object userInfo = authentication.getPrincipal(); boolean hasPermission = false; @@ -449,6 +457,62 @@ public class RbacAuthorityService { return false; } } + + /** + * 校验请求是否存在 + * + * @param request 请求 + */ + private void checkRequest(HttpServletRequest request) { + // 获取当前 request 的方法 + String currentMethod = request.getMethod(); + Multimap urlMapping = allUrlMapping(); + + for (String uri : urlMapping.keySet()) { + // 通过 AntPathRequestMatcher 匹配 url + // 可以通过 2 种方式创建 AntPathRequestMatcher + // 1:new AntPathRequestMatcher(uri,method) 这种方式可以直接判断方法是否匹配,因为这里我们把 方法不匹配 自定义抛出,所以,我们使用第2种方式创建 + // 2:new AntPathRequestMatcher(uri) 这种方式不校验请求方法,只校验请求路径 + AntPathRequestMatcher antPathMatcher = new AntPathRequestMatcher(uri); + if (antPathMatcher.matches(request)) { + if (!urlMapping.get(uri) + .contains(currentMethod)) { + throw new SecurityException(Status.HTTP_BAD_METHOD); + } else { + return; + } + } + } + + throw new SecurityException(Status.REQUEST_NOT_FOUND); + } + + /** + * 获取 所有URL Mapping,返回格式为{"/test":["GET","POST"],"/sys":["GET","DELETE"]} + * + * @return {@link ArrayListMultimap} 格式的 URL Mapping + */ + private Multimap allUrlMapping() { + Multimap urlMapping = ArrayListMultimap.create(); + + // 获取url与类和方法的对应信息 + Map handlerMethods = mapping.getHandlerMethods(); + + handlerMethods.forEach((k, v) -> { + // 获取当前 key 下的获取所有URL + Set url = k.getPatternsCondition() + .getPatterns(); + RequestMethodsRequestCondition method = k.getMethodsCondition(); + + // 为每个URL添加所有的请求方法 + url.forEach(s -> urlMapping.putAll(s, method.getMethods() + .stream() + .map(Enum::toString) + .collect(Collectors.toList()))); + }); + + return urlMapping; + } } ``` diff --git a/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/RbacAuthorityService.java b/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/RbacAuthorityService.java index f39eb14..1c25012 100644 --- a/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/RbacAuthorityService.java +++ b/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/config/RbacAuthorityService.java @@ -53,7 +53,7 @@ public class RbacAuthorityService { private RequestMappingHandlerMapping mapping; public boolean hasPermission(HttpServletRequest request, Authentication authentication) { - checkRequestNotFound(request); + checkRequest(request); Object userInfo = authentication.getPrincipal(); boolean hasPermission = false; @@ -97,7 +97,7 @@ public class RbacAuthorityService { * * @param request 请求 */ - private void checkRequestNotFound(HttpServletRequest request) { + private void checkRequest(HttpServletRequest request) { // 获取当前 request 的方法 String currentMethod = request.getMethod(); Multimap urlMapping = allUrlMapping();