如何在Spring Security 6中正确设置自定义的UsernamePasswordAuthenticationFilter的SecurityContextRepository?

7 浏览
0 Comments

如何在Spring Security 6中正确设置自定义的UsernamePasswordAuthenticationFilter的SecurityContextRepository?

从Spring Security 6.0开始,需要显式保存SecurityContextRepository:

https://docs.spring.io/spring-security/reference/migration/servlet/session-management.html#_require_explicit_saving_of_securitycontextrepository

这意味着,如果使用自定义的UsernamePasswordAuthenticationFilter,必须提供SecurityContextRepository以便持久化SecurityContext,如下所示:

@Component
public class InternalUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    @PostConstruct
    private void setup() {
        super.setSecurityContextRepository(
                new DelegatingSecurityContextRepository(
                        new RequestAttributeSecurityContextRepository(),
                        new HttpSessionSecurityContextRepository()));
    }
    //...
}

似乎只需要在AuthenticationFilter中指定SecurityContextRepository一次即可,尽管示例中的@Max在此处https://stackoverflow.com/a/75002996/13609359中也在SecurityFilterChain中设置了repository。

我已经测试了这两种变体,无论在FilterChain中是否指定SecurityContextRepository似乎都没有关系。是否为AuthenticationFilter和FilterChain使用一个bean或为每个创建新的repository似乎也没有关系,如下所示:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true)
public class WebSecurityConfig {
    @Bean
    public SecurityFilterChain mvcFilterChain(HttpSecurity http) throws Exception {
        return http
                .authorizeHttpRequests(authorize -> authorize
                        .shouldFilterAllDispatcherTypes(true)
                        .dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll()
                        .requestMatchers("/", "/login/**").permitAll()
                        .anyRequest().authenticated())
                .addFilterAt(internalUsernamePasswordAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                .securityContext(securityContext -> securityContext
                        .securityContextRepository(
                                new DelegatingSecurityContextRepository(
                                        new RequestAttributeSecurityContextRepository(),
                                        new HttpSessionSecurityContextRepository()
                                )))
                //...
    }
}

这似乎表明只使用AuthenticationFilter的repository,而忽略了FilterChain的repository。

因此,我认为在AuthenticationFilter中创建SecurityContextRepository就足够了。

所以我的问题是:

  1. 我理解得对吗?
  2. 还是我应该定义一个bean?
  3. 在SecurityFilterChain中设置这个bean是否有任何原因?

非常感谢任何帮助和澄清。

0