Skip to content

SecurityFilterChain 配置方式

Spring Security 6+ 的配置核心就是显式声明 SecurityFilterChain Bean。旧时代继承 WebSecurityConfigurerAdapter 的思路已经退出主线。

最小可用配置

java
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
                .csrf(csrf -> csrf.disable())
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/public/**", "/auth/**").permitAll()
                        .anyRequest().authenticated())
                .build();
    }
}

多条链并存

java
@Bean
@Order(1)
SecurityFilterChain apiChain(HttpSecurity http) throws Exception {
    return http
            .securityMatcher("/api/**")
            .csrf(csrf -> csrf.disable())
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(auth -> auth
                    .requestMatchers("/api/auth/**").permitAll()
                    .anyRequest().authenticated())
            .build();
}

@Bean
@Order(2)
SecurityFilterChain webChain(HttpSecurity http) throws Exception {
    return http
            .securityMatcher("/**")
            .formLogin(Customizer.withDefaults())
            .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
            .build();
}

运行时规则:

  • 先按 @Order 排序。
  • 再按 securityMatcher 判断命中。
  • 只使用第一条匹配链。

常见配套 Bean

java
@Bean
UserDetailsService userDetailsService() {
    return new InMemoryUserDetailsManager(
            User.withUsername("admin")
                    .password("{noop}123456")
                    .roles("ADMIN")
                    .build());
}

@Bean
PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

Boot 3 项目中的组织方式

text
security
  ├── SecurityConfig.java
  ├── JwtAuthenticationFilter.java
  ├── AuthenticationEntryPointImpl.java
  ├── AccessDeniedHandlerImpl.java
  └── JwtService.java

典型异常处理

java
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
            .exceptionHandling(ex -> ex
                    .authenticationEntryPoint((request, response, authException) -> {
                        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                    })
                    .accessDeniedHandler((request, response, accessDeniedException) -> {
                        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                    }))
            .build();
}