SecurityFilterChain中http.authorizeHttpRequests()失效:localhost重定向次数过多
问题:Spring Security 替换弃用的WebSecurityConfigurerAdapter后出现重定向循环
由于WebSecurityConfigurerAdapter已被弃用,我尝试用SecurityFilterChain filterChain(HttpSecurity http)替代configure(HttpSecurity http)方法。编写代码后,Chrome浏览器提示“localhost redirected you too many times”错误,控制台无报错,清除Cookie后问题仍未解决。
AppSecurityConfig.java
@Configuration public class AppSecurityConfig { @Autowired private UserDetailsService userDetailsService; @Bean public AuthenticationProvider authProvider() { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(userDetailsService); provider.setPasswordEncoder(new BCryptPasswordEncoder()); return provider; } // 尝试替换 configure(HttpSecurity http) 方法 @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeHttpRequests() .requestMatchers("/login").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login").permitAll() .and() .logout().invalidateHttpSession(true) .clearAuthentication(true) .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .logoutSuccessUrl("/logout-success").permitAll(); return http.build(); } }
注:因.authorizeRequests()已弃用,故使用.authorizeHttpRequests()。
HomeController.java
@Controller public class HomeController { @RequestMapping("/") public String home() { return "home.jsp"; } @RequestMapping("/login") public String loginPage() { return "login.jsp"; } @RequestMapping("/logout-success") public String logoutPage() { return "logout.jsp"; } }
login.jsp
<body> <h1>Login</h1> ${SPRING_SECURITY_LAST_EXCEPTION.message} <form action="login" method="post"> <table> <tr> <td>User:</td> <td><input type='text' name='username' value='' /></td> </tr> <tr> <td>Password:</td> <td><input type="password" name='password' /></td> </tr> <tr> <td><input type="submit" name='submit' value='submit' /></td> </tr> </table> </form> </body> </html>
解决方案
重定向循环的核心原因是表单登录的提交路径未被Spring Security识别为认证处理路径,导致登录请求被拦截后反复重定向到登录页。
修复代码
修改filterChain方法,显式指定登录处理路径:
@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeHttpRequests(auth -> auth .requestMatchers("/login", "/logout-success").permitAll() .anyRequest().authenticated() ) .formLogin(form -> form .loginPage("/login") // 自定义登录页路径 .loginProcessingUrl("/login") // 标记该路径为Spring Security认证处理入口 .permitAll() ) .logout(logout -> logout .invalidateHttpSession(true) .clearAuthentication(true) .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .logoutSuccessUrl("/logout-success") .permitAll() ); return http.build(); }
原理说明
- 未添加
loginProcessingUrl("/login")时,表单提交到/login会被Spring Security当作普通请求拦截,因未认证重定向到登录页,形成循环。 - 添加该配置后,Spring Security会将
/login路径识别为认证处理入口,直接处理用户名密码校验,不再触发重定向。
额外建议
除非有特殊需求,建议开启CSRF防护(去掉.csrf().disable()),并在登录表单中添加CSRF令牌:
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
内容的提问来源于stack exchange,提问作者Aafaque Ali
相关产品推荐
相关产品推荐

