使用@PreAuthorize搭配含特殊字符路径变量时触发异常问题排查
回答
1. 异常产生的原因
这是Spring Security路径匹配优先级与认证过滤器执行时机冲突导致的:
- 当路径变量包含
@这类特殊字符时,AntPathMatcher的匹配逻辑会提前触发方法级的@PreAuthorize权限校验 - 此时自定义的
CustomHeaderAuthenticationFilter还未执行,SecurityContext中没有Authentication对象,直接抛出AuthenticationCredentialsNotFoundException - 而路径变量无特殊字符时,Spring Security会先让请求走完认证过滤器流程,完成认证后再执行
@PreAuthorize校验,因此正常工作
简单来说就是特殊字符打乱了路径匹配顺序,让权限校验抢在了认证前面,导致上下文里没有合法的认证信息。
2. 解决方案(保留@PreAuthorize与路径变量)
有两种可靠方案可选:
方案一:调整自定义过滤器的执行顺序
把自定义过滤器移到SecurityContextPersistenceFilter之前,确保认证逻辑在任何权限校验前完成:
@Override protected void configure(final HttpSecurity http) throws Exception { http.csrf().disable().headers().disable() // 调整过滤器位置到SecurityContextPersistenceFilter之前 .addFilterBefore(new CustomHeaderAuthenticationFilter(), SecurityContextPersistenceFilter.class) .authorizeRequests() .antMatchers(AUTH_WHITELIST).permitAll() .anyRequest().authenticated(); }
方案二:为目标接口添加明确的路径匹配规则
在HttpSecurity里给目标接口添加一条明确的ant匹配规则,让Spring Security优先处理该路径的认证流程:
@Override protected void configure(final HttpSecurity http) throws Exception { http.csrf().disable().headers().disable().authorizeRequests() .antMatchers(AUTH_WHITELIST).permitAll() // 新增明确匹配规则,覆盖默认的anyRequest匹配顺序 .antMatchers("/v1/permissions/**/users/**").authenticated() .anyRequest().authenticated() .and() .addFilterBefore(new CustomHeaderAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); }
两种方案都能保证认证流程先于@PreAuthorize执行,让SecurityContext中存在合法的Authentication对象,解决异常问题。方案一更通用,适合全局调整;方案二更精准,仅针对目标接口生效。
内容的提问来源于stack exchange,提问作者Prakash K
相关产品推荐
相关产品推荐

