WebSecurityConfigurerAdapterの非推奨化対応:Spring Security 6.xの新しい設定方法
Spring Boot 2.7.0でWebSecurityConfigurerAdapter
が非推奨となり、多くの開発者が設定の移行に課題を感じています。本記事では、JWT認証を使用したSpring Security設定の最新の実装方法を詳しく解説します。
問題の概要
WebSecurityConfigurerAdapter
の非推奨化に伴い、従来の設定方法では以下のエラーが発生します:
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認証を使用した完全なセキュリティ設定の最新実装例です:
@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の設定変更
従来の方法:
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
新しい方法:
@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
Spring Bootが自動的にUserDetailsService
とPasswordEncoder
を検出し、適切なAuthenticationManager
を構築します。
2. HTTPセキュリティ設定の変更
従来の方法:
@Override
protected void configure(HttpSecurity http) throws Exception {
// 設定内容
}
新しい方法:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// 設定内容
return http.build();
}
3. 新しいラムダ式ベースのDSL
Spring Security 6では、より宣言的な設定が可能になりました:
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の実装
@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
アノテーションを使用します:
@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への移行は、最初は困難に感じるかもしれませんが、新しい設定方法はより柔軟で明示的です。主要な変更点は:
WebSecurityConfigurerAdapter
の継承をやめるSecurityFilterChain
Beanを定義するAuthenticationManager
はAuthenticationConfiguration
から取得する- ラムダ式ベースのDSLを使用する
- アノテーションを最新のものに更新する
これらの変更により、より現代的なセキュリティ設定が可能になり、アプリケーションの保守性と拡張性が向上します。