Spring Security Basic Auth密码更新后旧凭据仍可访问问题排查
问题原因
- 默认情况下Spring Security开启了会话管理,Basic认证通过后,用户的身份信息会被存入服务端Session,后续请求携带对应的
JSESSIONIDCookie即可完成身份校验,无需再重新校验Basic Auth的凭据,这就是你第一次输入密码后后续请求都无需认证的核心原因。 - 你之前配置会话无状态后问题解决,本质是禁用了Session存储认证信息的逻辑,强制每次请求都校验
Authorization请求头里的凭据。但你后续新增InMemoryUserDetailsManager相关代码时,没有保留无状态会话的配置,所以回到了默认的会话复用逻辑,问题复现。 - 至于服务端重启修改密码后旧凭据仍能生效,大概率是两种情况:一是浏览器缓存了旧的
Authorization请求头,每次请求自动携带,而你修改密码后的代码未正常生效(比如未重新打包启动、存在配置覆盖等问题);二是你开启了会话持久化,服务端重启后Session没有被清空,仍然可以读取到之前存储的认证信息。
解决方案
你只需要在原有HttpSecurity配置里明确指定会话策略为无状态即可,修改后的完整配置如下:
import org.springframework.security.config.http.SessionCreationPolicy; @Component @EnableWebSecurity public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter { private final PasswordEncoder passwordEncoder; @Autowired public ApplicationSecurityConfig(PasswordEncoder passwordEncoder) { this.passwordEncoder = passwordEncoder; } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest() .authenticated() .and() .httpBasic() .and() // 核心配置:设置会话为无状态,不创建、不使用Session存储认证信息 .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); } @Override @Bean protected UserDetailsService userDetailsService() { UserDetails user = User .builder() .username("admin") .password(passwordEncoder.encode("admin")) .roles("ADMINISTRATOR") .build(); return new InMemoryUserDetailsManager(user); } }
配置完成后验证时需要注意:
- 先清除浏览器之前缓存的Cookie和
Authorization凭据,或者使用无痕模式测试,避免旧缓存影响验证结果 - 后续修改密码只需调整
UserDetails构建逻辑重启服务即可,因为每次请求都会重新校验凭据,旧的凭据会立刻失效。
内容的提问来源于stack exchange,提问作者Tokyo
相关产品推荐
相关产品推荐

