You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Security HTTP Basic认证如何强制每次请求重新校验?

解决Spring Security HTTP Basic认证每次请求重新校验的问题

问题原因

Spring Security默认会把认证成功的Authentication对象存入会话(Session)的SecurityContext中,后续请求会直接复用这个已认证对象,不会重新校验请求头里的用户名密码,这就是日志里出现“Did not re-authenticate”的原因。

解决方案

1. 禁用会话持久化,强制每次请求重新认证

在SecurityFilterChain配置中添加会话管理策略,设置为STATELESS(无状态),让Spring Security不在会话中保存认证状态,每次请求都必须重新校验凭证:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    log.info("In securityFilterChain with HttpSecurity");
    http
            .csrf().disable()
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 关键配置
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .httpBasic()
            .authenticationEntryPoint(authEntryPoint);
    return http.build();
}

2. 确保用户信息能实时更新

你当前使用InMemoryUserDetailsManager存储用户,要动态修改密码的话,必须更新内存中的用户对象,而不是每次创建新的InMemoryUserDetailsManager实例。可以把它单独注册为Bean,修改密码时调用其updateUser方法:

@Bean
public InMemoryUserDetailsManager userDetailsService() {
    UserDetails user = User.builder()
            .username("basic")
            .password(encoder.encode("basic123"))
            .roles("USER")
            .build();
    return new InMemoryUserDetailsManager(user);
}

// 修改密码时调用此方法更新用户信息
public void updateUserPassword(String username, String newPassword) {
    UserDetails existingUser = userDetailsService().loadUserByUsername(username);
    UserDetails updatedUser = User.builder()
            .username(existingUser.getUsername())
            .password(encoder.encode(newPassword))
            .roles(existingUser.getAuthorities().stream()
                    .map(GrantedAuthority::getAuthority)
                    .map(role -> role.replace("ROLE_", ""))
                    .toArray(String[]::new))
            .build();
    userDetailsService().updateUser(updatedUser);
}

3. 修正AuthenticationManager配置

你当前的AuthenticationManagerBean重复构建了UserDetailsService,会导致和业务中使用的实例不一致,修改后的用户信息无法生效。调整为注入已有的UserDetailsService:

@Bean 
public AuthenticationManager authenticationManager(HttpSecurity http, UserDetailsService userDetailsService) throws Exception {
    return http.getSharedObject(AuthenticationManagerBuilder.class)
            .userDetailsService(userDetailsService)
            .and()
            .build();
}

完成以上配置后,每次请求都会重新解析HTTP Basic头的用户名密码,调用UserDetailsService获取最新用户信息校验,使用旧密码时会返回401 Unauthorized。

内容的提问来源于stack exchange,提问作者kakoli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 05:25:51