JDBC会话和Spring Security的Sping Boot 3迁移不起作用

lyr7nygr  于 2023-01-05  发布在  Spring
关注(0)|答案(1)|浏览(145)

这是Sping Boot 版本3.0.1的问题。这在版本2.7.5中运行得非常好。
我的应用程序使用Spring Security和JDBC会话。因此,我将X-Auth-Token保存在数据库(PostgreSQL)的spring_session表中。我实现了UserDetailsService接口,以便在调用登录控制器方法时从数据库中获取用户。
当迁移到新的Sping Boot 3版本时,主要的变化发生在WebSecurityConfig类中。以前它是从WebSecurityConfigurerAdapter类扩展而来的。所以我知道问题出在这个类的某个地方。
下面我将复制并粘贴WebSecurityConfig类的旧版本2.7.5(运行良好)和新版本3.0.1:

Spring Boot 版本2.7.5

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;

    @Autowired
    UserDetailsService userDetailsService;

    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {        
        http
            .csrf().disable()
            .exceptionHandling()
                .authenticationEntryPoint(restAuthenticationEntryPoint)
                .and()
            .cors()
                .and()
            .httpBasic()
                .and()
            .authorizeRequests()
                .antMatchers("/api/usermanager/auth/login").permitAll()
                .antMatchers(HttpMethod.GET, "/api/usermanager/image/org/**").permitAll()
                .antMatchers("/invalidSession*").anonymous()              
                .anyRequest().authenticated()
                .and()
            .formLogin()              
                .permitAll()
                .failureHandler(authenticationFailureHandler)               
                .and()
            .sessionManagement()
                .sessionFixation()
                .migrateSession()               
                .maximumSessions(1)
                .expiredUrl("/sessionExpired.html")
                .maxSessionsPreventsLogin(false);
    }

    @Override
    public void configure(WebSecurity web) {
        web
            .ignoring()
                .antMatchers("/docs/**", "/resources/**", "/static/**");
    }

    @Bean
    public AuthenticationFailureHandler myFailureHandler() {
        return new CustomAuthenticationFailureHandler();
    }

    @Bean
    public HttpSessionIdResolver httpSessionStrategy() {
        return HeaderHttpSessionIdResolver.xAuthToken();
    }

    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth
            .inMemoryAuthentication()
                .withUser("client")
                    .password(passwordEncoder.encode("Client@Venturi"))
                    .roles("USER");      
        var daoAC = new DaoAuthenticationConfigurer(userDetailsService);
        daoAC.passwordEncoder(passwordEncoder);
        auth.apply(daoAC);
    }
}

Spring Boot 版本3.0.1

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig {

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public AuthenticationManager authenticationManager(HttpSecurity http,
                                                       PasswordEncoder passwordEncoder)
            throws Exception {
        var daoAC = new DaoAuthenticationConfigurer(userDetailsService);
        daoAC.passwordEncoder(passwordEncoder);

        var builder = http.getSharedObject(AuthenticationManagerBuilder.class);
        builder.apply(daoAC);
        return builder.build();    
    }

    private static final String[] AUTH_WHITELIST = {
            "/api/usermanager/auth/login"           
    };

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {       
        http
            .csrf().disable()
            .exceptionHandling()              
                .and()
            .cors()
                .and()
            .httpBasic()
                .and()
            .authorizeHttpRequests(
                        requests -> requests.
                        requestMatchers(AUTH_WHITELIST).permitAll()
                                .anyRequest().authenticated()
                )
            .sessionManagement()
                .sessionFixation()
                .migrateSession()               
                .maximumSessions(1)
                .expiredUrl("/sessionExpired.html")
                .maxSessionsPreventsLogin(false);

        return http.build();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers(HttpMethod.GET,
                "/docs/**", "/resources/**", "/static/**"
        );
    }

    @Bean
    public AuthenticationFailureHandler myFailureHandler() {
        return new CustomAuthenticationFailureHandler();
    }

    @Bean
    public HttpSessionIdResolver httpSessionStrategy() {
        return HeaderHttpSessionIdResolver.xAuthToken();
    }

    @Bean
    public HttpSessionIdResolver httpSessionIdResolver() {
        return HeaderHttpSessionIdResolver.xAuthToken();
    }

    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }
}

当我调用上面的auth/login控制器API时,我得到了填充在spring_session表中的会话ID,但是该表中的principal_namenull,我希望您知道spring_session表是Spring Session创建的用于保存会话信息的默认表。
在2.7.5版本中,principal_name将被保存(用户登录名)。因此,在后续请求中,我可以通过在HTTP请求头中传递x-auth-token来获取用户。因此,现在我的问题是,当我调用上述控制器API时,principal_name始终是spring_session表中的null
在将WebSecurityConfig类转换为Sping Boot 版本3时,有人能看到我是否做错了什么吗?

u91tlkcl

u91tlkcl1#

与以前版本的差异是由于以下更改:https://github.com/spring-projects/spring-security/issues/11110
您可以使用自动保存SecurityContextHolder设置的旧策略(已弃用):

http.securityContext((securityContext) -> securityContext.requireExplicitSave(false))

相关问题