Skip to content

WebSecurityConfigurerAdapterの非推奨化対応:Spring Security 6.xの新しい設定方法

Spring Boot 2.7.0でWebSecurityConfigurerAdapterが非推奨となり、多くの開発者が設定の移行に課題を感じています。本記事では、JWT認証を使用したSpring Security設定の最新の実装方法を詳しく解説します。

問題の概要

WebSecurityConfigurerAdapterの非推奨化に伴い、従来の設定方法では以下のエラーが発生します:

java
org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration'
// ... 詳細なエラーメッセージ ...
Cannot apply org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration$EnableGlobalAuthenticationAutowiredConfigurer

このエラーは、新しいSpring Securityの設定方法に適切に移行できていない場合に発生します。

推奨される解決策

基本的なセキュリティ設定の移行

以下は、JWT認証を使用した完全なセキュリティ設定の最新実装例です:

java
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
@RequiredArgsConstructor
public class SecurityConfig {
    
    private final UserDetailsServiceImpl userDetailsService;
    private final AuthEntryPointJwt unauthorizedHandler;
    private final AuthTokenFilter authenticationJwtTokenFilter;

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

    @Bean
    public AuthenticationManager authenticationManager(
            AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())
            .exceptionHandling(exp -> exp.authenticationEntryPoint(unauthorizedHandler))
            .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/auth/**").permitAll()
                .requestMatchers("/api/test/**").permitAll()
                .requestMatchers("/api/v1/**").permitAll()
                .anyRequest().authenticated()
            );
        
        http.addFilterBefore(authenticationJwtTokenFilter, 
            UsernamePasswordAuthenticationFilter.class);
        
        return http.build();
    }
}

重要な変更点

  • @EnableGlobalMethodSecurity@EnableMethodSecurity に変更
  • antMatchers()requestMatchers() に変更
  • configure(HttpSecurity http)filterChain(HttpSecurity http) メソッドに変更
  • AuthenticationManagerの取得方法が変更

主な変更点の詳細解説

1. AuthenticationManagerの設定変更

従来の方法

java
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService)
        .passwordEncoder(passwordEncoder());
}

新しい方法

java
@Bean
public AuthenticationManager authenticationManager(
        AuthenticationConfiguration authenticationConfiguration) throws Exception {
    return authenticationConfiguration.getAuthenticationManager();
}

Spring Bootが自動的にUserDetailsServicePasswordEncoderを検出し、適切なAuthenticationManagerを構築します。

2. HTTPセキュリティ設定の変更

従来の方法

java
@Override
protected void configure(HttpSecurity http) throws Exception {
    // 設定内容
}

新しい方法

java
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    // 設定内容
    return http.build();
}

3. 新しいラムダ式ベースのDSL

Spring Security 6では、より宣言的な設定が可能になりました:

java
http
    .csrf(csrf -> csrf.disable())
    .exceptionHandling(exp -> exp.authenticationEntryPoint(unauthorizedHandler))
    .sessionManagement(session -> session
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
    .authorizeHttpRequests(auth -> auth
        .requestMatchers("/public/**").permitAll()
        .anyRequest().authenticated()
    );

カスタムUserDetailsServiceの実装

java
@Service
@RequiredArgsConstructor
public class CustomUserDetailService implements UserDetailsService {

    private final UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) 
            throws UsernameNotFoundException {
        
        User user = userRepository.findByUsername(username)
            .orElseThrow(() -> new UsernameNotFoundException(username));

        return User.builder()
            .username(user.getEmail())
            .password(user.getPassword())
            .authorities(convertAuthorities(user.getRoles()))
            .build();
    }

    private Set<GrantedAuthority> convertAuthorities(Set<Role> roles) {
        return roles.stream()
            .map(role -> new SimpleGrantedAuthority(role.getName()))
            .collect(Collectors.toSet());
    }
}

複数SecurityFilterChainの設定

異なるセキュリティポリシーを適用する場合、@Orderアノテーションを使用します:

java
@Configuration
@Order(1)
public class ActuatorSecurityConfig {

    @Bean
    public SecurityFilterChain actuatorFilterChain(HttpSecurity http) throws Exception {
        http
            .securityMatcher(EndpointRequest.toAnyEndpoint())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers(EndpointRequest.to("health", "info")).permitAll()
                .anyRequest().hasRole("ADMIN")
            )
            .httpBasic(Customizer.withDefaults());
        
        return http.build();
    }
}

よくある質問

Q: なぜWebSecurityConfigurerAdapterは非推奨になったのですか?

A: より柔軟なコンポーネントベースの設定を可能にするため、また設定の複雑さを軽減するためです。新しいアプローチでは、複数のSecurityFilterChainを定義でき、よりモジュール化された設定が可能になります。

Q: 移行時に最も注意すべき点は何ですか?

A: AuthenticationManagerの設定方法と、HTTPセキュリティ設定のメソッドシグネチャの変更です。また、antMatchersからrequestMatchersへの移行も重要です。

まとめ

Spring Security 6.xへの移行は、最初は困難に感じるかもしれませんが、新しい設定方法はより柔軟で明示的です。主要な変更点は:

  1. WebSecurityConfigurerAdapterの継承をやめる
  2. SecurityFilterChain Beanを定義する
  3. AuthenticationManagerAuthenticationConfigurationから取得する
  4. ラムダ式ベースのDSLを使用する
  5. アノテーションを最新のものに更新する

これらの変更により、より現代的なセキュリティ設定が可能になり、アプリケーションの保守性と拡張性が向上します。