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 2c74b2f..f39eb14 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 @@ -1,7 +1,11 @@ package com.xkcoding.rbac.security.config; import cn.hutool.core.util.StrUtil; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; import com.xkcoding.rbac.security.common.Consts; +import com.xkcoding.rbac.security.common.Status; +import com.xkcoding.rbac.security.exception.SecurityException; import com.xkcoding.rbac.security.model.Permission; import com.xkcoding.rbac.security.model.Role; import com.xkcoding.rbac.security.repository.PermissionDao; @@ -12,10 +16,16 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import javax.servlet.http.HttpServletRequest; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; /** @@ -39,7 +49,12 @@ public class RbacAuthorityService { @Autowired private PermissionDao permissionDao; + @Autowired + private RequestMappingHandlerMapping mapping; + public boolean hasPermission(HttpServletRequest request, Authentication authentication) { + checkRequestNotFound(request); + Object userInfo = authentication.getPrincipal(); boolean hasPermission = false; @@ -76,4 +91,60 @@ public class RbacAuthorityService { return false; } } + + /** + * 校验请求是否存在 + * + * @param request 请求 + */ + private void checkRequestNotFound(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; + } } \ No newline at end of file diff --git a/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/controller/TestController.java b/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/controller/TestController.java index 6c93ff9..da05212 100644 --- a/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/controller/TestController.java +++ b/spring-boot-demo-rbac-security/src/main/java/com/xkcoding/rbac/security/controller/TestController.java @@ -2,10 +2,7 @@ package com.xkcoding.rbac.security.controller; import com.xkcoding.rbac.security.common.ApiResponse; import lombok.extern.slf4j.Slf4j; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; /** *

@@ -35,4 +32,10 @@ public class TestController { log.info("测试列表添加"); return ApiResponse.ofMessage("测试列表添加"); } + + @PutMapping("/{id}") + public ApiResponse update(@PathVariable Long id) { + log.info("测试列表修改"); + return ApiResponse.ofSuccess("测试列表修改"); + } }