Spring Security授权URL未进入自定义AbstractSecurityInterceptor过滤器排查
自定义JWT授权过滤器未生效的问题排查
我来帮你分析下代码里的问题,主要集中在配置类的重复配置和过滤器的依赖注入/逻辑冗余这两个方面:
首先看配置类的问题
- 重复调用
authorizeRequests():你连续调用了两次.authorizeRequests(),这会导致Spring Security的规则配置被覆盖或者逻辑混乱,应该把所有的URL授权规则合并到同一个.authorizeRequests()块中。 - 手动new过滤器导致依赖注入失效:你在
addFilterBefore里直接new JWTAuthenticationFilter(),这个对象不受Spring容器管理,所以里面的@Autowired的securityMetadataSource和smcAccessDecisionManager都会是null,过滤器的核心逻辑根本跑不起来。 - 多余的
super.configure(web):在WebSecurity的配置里调用父类方法,可能会引入默认的忽略规则,干扰自定义过滤器的执行。
再看过滤器的问题
- 重复调用
super.beforeInvocation(object):你在invoke方法里先调用了一次super.beforeInvocation,然后又手动调用了smcAccessDecisionManager.decide,最后又调用了一次super.beforeInvocation——这不仅冗余,而且super.beforeInvocation内部已经会自动调用决策管理器的decide方法,手动调用完全没必要,还会导致重复校验。 - 依赖注入方式不合理:因为过滤器是手动new的,
@Autowired根本不生效,必须把过滤器注册为Spring Bean,用构造注入或者Spring管理的方式获取依赖。
修正后的代码示例
配置类修正版
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { // 注入Spring管理的过滤器Bean @Autowired private JWTAuthenticationFilter jwtAuthenticationFilter; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() // 合并所有授权规则到一个authorizeRequests块 .authorizeRequests() .antMatchers(HttpMethod.POST, "/user/login", "/user/sso/login").permitAll() .antMatchers(HttpMethod.GET, "/pos/findAllList").authenticated() .anyRequest().authenticated() .and() // 使用注入的过滤器,而不是手动new .addFilterBefore(jwtAuthenticationFilter, FilterSecurityInterceptor.class) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); } @Override public void configure(WebSecurity web) throws Exception { // 去掉super调用,只保留自定义忽略规则 web.ignoring() .antMatchers("/admin/swagger/**"); } }
过滤器修正版
@Log4j2 @Component // 注册为Spring Bean,让Spring管理依赖 public class JWTAuthenticationFilter extends AbstractSecurityInterceptor implements Filter { private final FilterInvocationSecurityMetadataSource securityMetadataSource; private final SmcAccessDecisionManager smcAccessDecisionManager; // 构造注入,确保依赖不为null public JWTAuthenticationFilter(FilterInvocationSecurityMetadataSource securityMetadataSource, SmcAccessDecisionManager smcAccessDecisionManager) { this.securityMetadataSource = securityMetadataSource; this.smcAccessDecisionManager = smcAccessDecisionManager; super.setAccessDecisionManager(smcAccessDecisionManager); } @Override public void init(FilterConfig filterConfig) throws ServletException { // 构造函数已经设置了AccessDecisionManager,这里不需要重复操作 } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { log.info("进入SmcSecurityFilter"); FilterInvocation fi = new FilterInvocation(request, response, chain); invoke(fi); } public void invoke(FilterInvocation object) throws IOException, ServletException { // 只调用一次beforeInvocation,内部会自动完成授权校验 InterceptorStatusToken token = super.beforeInvocation(object); try { object.getChain().doFilter(object.getRequest(), object.getResponse()); } finally { super.afterInvocation(token, null); } } @Override public Class<?> getSecureObjectClass() { return FilterInvocation.class; } @Override public SecurityMetadataSource obtainSecurityMetadataSource() { return this.securityMetadataSource; } @Override public void destroy() { } }
关键修正点说明
- 合并
authorizeRequests配置,避免规则冲突; - 将过滤器注册为Spring Bean,通过构造注入获取依赖,解决
@Autowired失效的问题; - 移除过滤器中重复的授权校验逻辑,依赖
AbstractSecurityInterceptor的默认流程完成授权; - 去掉
WebSecurity配置中的父类调用,确保自定义忽略规则生效。
内容的提问来源于stack exchange,提问作者kate
相关产品推荐
相关产品推荐

