Below is the SecurityFilterChain
bean created according to the new Spring Security 6 / Spring boot 3 documentation. However, requestMatchers -> AntPathRequestMatcher -> permitAll
is not working. Every request is reaching OncePerRequestFilter
. Please let me know if this is expected or if something is wrong.
Code:
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableMethodSecurity
public class WebSecurityConfig {
List<String> publicApis = List.of("/generate/**", "validated/**");
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors()
.configurationSource(corsConfigurationSource())
.and()
.csrf()
.disable()
.formLogin()
.disable()
.httpBasic()
.disable()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint())
.and()
.authorizeHttpRequests(
r -> r.requestMatchers(
publicApis().stream()
.map(AntPathRequestMatcher::new)
.toArray(RequestMatcher[]::new)
)
.permitAll()
.anyRequest()
.authenticated()
)
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().requestMatchers(publicApis.toArray(String[]::new));
}
}
SecurityFilter class:
@Component
@Slf4j
@RequiredArgsConstructor
public class SecurityFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
log.info("request:{}", request); // all requests are logging including `/generate/a` or `/validate/1`
}
}
Ideally /generate/a
or /validate/1
should not go to SecurityFilter. Still, there are going for JWT validation. How to avoid public APIs to bypass SecurityFilter.
Thanks in Advance.
CodePudding user response:
Your SecurityFilter
is a @Component
, therefore the filter will be picked up by Spring Boot and added to the filter chain.
Note that the filter chain that I mentioned is not the same chain as Spring Security, which is the SecurityFilterChain
. Spring Security will not invoke the SecurityFilterChain
for the endpoints you mentioned, because you did:
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().requestMatchers(publicApis.toArray(String[]::new));
}
I believe that since you are ignoring those endpoints, you do not need to permitAll
them (those are different things).
One way to solve this is by adding the SecurityFilter
to the SecurityFilterChain
(which is not invoked for those endpoints):
- Remove
@Component
from yourSecurityFilter
- Do
http.addFilter(Before/After/At)(new SecurityFilter(), BeforeFilter.class)