Spring Security:如何在Filter中获取接口的权限配置
核心思路:通过Spring的RequestMappingHandlerMapping匹配当前请求对应的控制器方法,再从方法上提取@PreAuthorize注解的权限表达式并解析。
具体实现步骤
注入RequestMappingHandlerMapping
在自定义过滤器中注入该Bean,用于根据请求定位到对应的控制器处理方法。获取当前请求的HandlerMethod
在doFilterInternal方法中,通过RequestMappingHandlerMapping获取请求对应的HandlerExecutionChain,进而得到HandlerMethod实例。解析@PreAuthorize注解中的权限
从HandlerMethod上提取@PreAuthorize注解,解析其中的SpEL表达式,提取出目标权限值。
完整代码示例
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerExecutionChain; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; public class AuthTokenFilter extends OncePerRequestFilter { @Autowired private RequestMappingHandlerMapping requestMappingHandlerMapping; @Override protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) throws IOException, ServletException { try { // 获取当前请求对应的控制器方法链 HandlerExecutionChain handlerChain = requestMappingHandlerMapping.getHandler(req); if (handlerChain != null && handlerChain.getHandler() instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handlerChain.getHandler(); // 提取方法上的@PreAuthorize注解 PreAuthorize preAuthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class); if (preAuthorize != null) { String expression = preAuthorize.value(); // 解析hasAuthority('XXX')格式的权限表达式 Pattern pattern = Pattern.compile("hasAuthority\\('([^']+)'\\)"); Matcher matcher = pattern.matcher(expression); if (matcher.find()) { String requiredAuthority = matcher.group(1); // 此处可根据业务需求使用获取到的权限值 System.out.println("当前接口所需权限:" + requiredAuthority); } } } } catch (Exception e) { // 处理请求未匹配到控制器方法等异常情况 e.printStackTrace(); } // 继续执行过滤器链 filterChain.doFilter(req, res); } }
复杂表达式处理(可选)
如果@PreAuthorize使用hasAnyAuthority等多权限表达式,可调整解析逻辑:
import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; // ... 其他代码 if (preAuthorize != null) { String expression = preAuthorize.value(); // 解析hasAnyAuthority('AUTH1','AUTH2')格式 Pattern anyPattern = Pattern.compile("hasAnyAuthority\\(([^)]+)\\)"); Matcher anyMatcher = anyPattern.matcher(expression); if (anyMatcher.find()) { String authStr = anyMatcher.group(1); String[] authorities = authStr.replace("'", "").split(","); for (String auth : authorities) { System.out.println("所需权限:" + auth.trim()); } } }
注意事项
- 确保
AuthTokenFilter被Spring容器管理(添加@Component注解),并配置合理的过滤器执行顺序。 - 若表达式逻辑复杂,建议使用Spring的
SpelExpressionParser进行专业解析,避免正则匹配的局限性。
内容的提问来源于stack exchange,提问作者Beno
相关产品推荐
相关产品推荐

