Spring Boot 3.0.2登录后重定向至错误页问题求助
Spring Boot 3升级后登录重定向至错误页问题排查
问题背景
在Spring Boot 2.7.7(Java 17)中,以下SecurityFilterChain配置运行正常:访问/digital/**路径时会触发登录,登录完成后自动重定向至目标页面。
http .authorizeHttpRequests() .antMatchers("/", "/js/**", "/css/**", "/img/**", "/webjars/**").permitAll() .antMatchers("/digital/**").hasRole("DIGITAL") .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll()
升级至Spring Boot 3.0.2后,仅将.antMatchers替换为.requestMatchers,并完成javax到jakarta的包迁移。但出现异常:访问/digital/**页面时能正常触发登录,登录后却跳转到默认错误页;但手动重试目标链接时,可正常访问。
请求映射日志显示,登录后的重定向请求多次匹配到BasicErrorController,而非目标的editRecord方法。
原因分析
问题源于Spring Boot 3对应的Spring Security 6的几处行为变化:
- 路径匹配器逻辑差异:
requestMatchers默认使用Servlet原生路径匹配规则,而旧版antMatchers依赖Spring MVC的路径匹配逻辑(如自动忽略后缀、支持矩阵变量等),可能导致/digital/**的匹配范围变化,影响请求缓存的保存与恢复。 - 请求缓存默认配置调整:Spring Security 6对
HttpSessionRequestCache的默认行为做了修改,未认证时的请求可能无法被正确保存,登录后无法重定向至原始请求。 - 表单登录成功处理器隐式变更:默认的登录成功处理器逻辑调整,未正确触发保存请求的重定向逻辑。
解决方案
方案1:改用Spring MVC兼容的路径匹配器
将requestMatchers替换为mvcMatchers,保持与旧版antMatchers一致的路径匹配逻辑:
http .authorizeHttpRequests(auth -> auth .requestMatchers("/", "/js/**", "/css/**", "/img/**", "/webjars/**").permitAll() .mvcMatchers("/digital/**").hasRole("DIGITAL") // 使用mvcMatchers替代requestMatchers .anyRequest().authenticated() ) .formLogin(form -> form .loginPage("/login") .permitAll() )
方案2:显式配置请求缓存
强制启用HttpSessionRequestCache并允许创建会话,确保未认证请求被正确保存:
http .authorizeHttpRequests(auth -> auth .requestMatchers("/", "/js/**", "/css/**", "/img/**", "/webjars/**").permitAll() .requestMatchers("/digital/**").hasRole("DIGITAL") .anyRequest().authenticated() ) .requestCache(requestCache -> requestCache .httpSessionRequestCache(cache -> cache .createSessionAllowed(true) // 允许为保存请求创建会话 ) ) .formLogin(form -> form .loginPage("/login") .permitAll() )
方案3:指定登录成功处理器
显式使用SavedRequestAwareAuthenticationSuccessHandler,确保登录后优先重定向至保存的原始请求:
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; // ... http .authorizeHttpRequests(auth -> auth .requestMatchers("/", "/js/**", "/css/**", "/img/**", "/webjars/**").permitAll() .requestMatchers("/digital/**").hasRole("DIGITAL") .anyRequest().authenticated() ) .formLogin(form -> form .loginPage("/login") .permitAll() .successHandler(new SavedRequestAwareAuthenticationSuccessHandler()) // 显式指定成功处理器 )
内容的提问来源于stack exchange,提问作者thesoretoothsayer
相关产品推荐
相关产品推荐

