Spring Security 6登录异常求助:自定义FilterChain下的奇怪跳转现象
Spring Security 6 登录请求拦截与重定向问题解析
核心问题:loginProcessingUrl与自定义登录接口冲突
你遇到的问题本质是Spring Security的表单登录拦截机制和你自定义的/login1 POST接口发生了路径冲突:
- 当配置
.loginProcessingUrl("/login1")时,Spring Security会自动通过UsernamePasswordAuthenticationFilter拦截所有发往/login1的POST请求,自行接管登录验证流程——这意味着你UserController里的@PostMapping("/login1")根本不会被执行,请求提前被Security过滤器链拦截。此时若验证失败,Security会按配置的failureUrl("/login?error=true")重定向,但你的登录页实际路径是/login1,路径不匹配导致302循环重定向。 - 改为
.loginProcessingUrl("/login1!")时,Security过滤器仅拦截这个特殊路径,而你的表单提交目标是/login1,请求会正常落到自定义控制器接口上,由你手动调用AuthenticationManager完成验证,因此程序能正常运行。至于/login1!未在控制器定义也无影响,因为你实际并未触发该路径的请求,这个配置仅告知Security:若有请求到该路径则由其处理登录。
现有写法的隐患
你的实现绕开了Spring Security的标准表单登录流程,手动在控制器处理验证,会带来以下问题:
- 重复造轮子:Security已封装完整的登录验证、异常处理、会话管理逻辑,手动实现易遗漏细节。
- 状态与会话冲突:你配置了
sessionCreationPolicy(SessionCreationPolicy.STATELESS)(无状态),但表单登录本质依赖会话,混合配置会导致偶尔的重定向异常(即你遇到的空白页/登录页重定向问题)。
正确解决方案
方案1:使用Spring Security标准表单登录流程(推荐)
删除控制器中的@PostMapping("/login1"),让Security完全接管登录验证:
@Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{ return http .csrf(config -> config.disable()) .authorizeHttpRequests(auth -> auth .requestMatchers("/login1").permitAll() // 允许未认证访问登录页 .anyRequest().authenticated() ) .formLogin(form -> form .loginPage("/login1") // 指定自定义登录页路径 .loginProcessingUrl("/login1") // 表单提交路径,由Security处理 .defaultSuccessUrl("/hello", true) // 登录成功后跳转页面 .failureUrl("/login1?error=true") // 登录失败跳转回登录页并携带错误参数 ) .logout(logout -> logout.permitAll()) // 表单登录依赖会话,不能使用STATELESS .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)) .build(); }
同时修改登录页的错误提示参数,匹配上述failureUrl配置:
<div th:if="${param.error}"> Invalid username and password. </div>
方案2:坚持自定义登录接口(适合REST场景)
若想完全自定义登录逻辑,应采用REST风格接口,而非表单登录:
- 移除
formLogin配置,改用无状态模式:
@Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{ return http .csrf(config -> config.disable()) .authorizeHttpRequests(auth -> auth .requestMatchers("/login1").permitAll() .anyRequest().authenticated() ) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .build(); }
- 保留控制器中的
@PostMapping("/login1"),登录成功后返回令牌或手动处理跳转(无状态模式下不推荐跳转)。
偶尔重定向到空白页/登录页的原因
该问题源于你同时配置了STATELESS无状态会话和表单登录:
- 表单登录成功后,Security会创建会话保存认证信息,但
STATELESS禁止会话创建,导致认证状态无法持久化。 - 后续请求时,Security无法识别已认证用户,会重定向到登录页;偶尔的空白页是会话状态不一致引发的异常。
解决办法是统一会话策略:表单登录使用IF_REQUIRED或ALWAYS,REST接口使用STATELESS。
内容的提问来源于stack exchange,提问作者Alexander Tupiza
相关产品推荐
相关产品推荐

