Spring Boot Thymeleaf自定义登录页面重定向循环问题求助
自定义Spring Security登录页面出现重定向循环问题
在Spring Boot Thymeleaf项目中实现自定义登录页面,访问应用根路径时会重定向到http://localhost:8080/login.html,但未显示登录表单,反而出现错误:“页面未正确重定向,Firefox检测到服务器对该地址的请求重定向方式将永远无法完成”。添加自定义登录前,默认登录弹窗可正常使用,问题出在自定义登录的配置中。
我的WebSecurityConfig配置
@EnableWebSecurity @Configuration public class WebSecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.csrf().disable(); http .authorizeRequests() .antMatchers("/login*", "/", "/search", "/browse", "/recipes/**", "/tags/**", "/edit/**", "/delete/**") .hasRole("ADMIN") .antMatchers("/login*", "/", "/search", "/browse", "/recipes/**", "/tags/**") .hasRole("USER") .anyRequest() .authenticated() .and() .formLogin().loginPage("/login.html") .defaultSuccessUrl("/", true) .failureUrl("/login.html?error=true"); return http.build(); } @Bean public PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } @Bean public InMemoryUserDetailsManager userDetailsService() { UserDetails user = User.withUsername("foote").password(passwordEncoder().encode("userpassword")).roles("USER") .build(); UserDetails admin = User.withUsername("admin").password(passwordEncoder().encode("adminpassword")) .roles("USER", "ADMIN").build(); return new InMemoryUserDetailsManager(user, admin); } }
我的login.html代码
<html> <head></head><body> <h1>Login</h1> <form name='f' 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 name="submit" type="submit" value="submit" /></td> </tr> </table> </form> </body> </html>
Spring Security DEBUG日志(重定向循环片段)
2022-11-19T10:07:06.116 [http-nio-8080-exec-1] [DEBUG] [o.s.security.web.FilterChainProxy] Securing GET / 2022-11-19T10:07:06.119 [http-nio-8080-exec-1] [DEBUG] [o.s.s.w.c.SecurityContextPersistenceFilter] Set SecurityContextHolder to empty SecurityContext 2022-11-19T10:07:06.121 [http-nio-8080-exec-1] [DEBUG] [o.s.s.w.a.AnonymousAuthenticationFilter] Set SecurityContextHolder to anonymous SecurityContext 2022-11-19T10:07:06.127 [http-nio-8080-exec-1] [DEBUG] [o.s.s.w.a.i.FilterSecurityInterceptor] Failed to authorize filter invocation [GET /] with attributes [hasRole('ROLE_USER')] 2022-11-19T10:07:06.135 [http-nio-8080-exec-1] [DEBUG] [o.s.s.w.s.HttpSessionRequestCache] Saved request http://localhost:8080/ to session 2022-11-19T10:07:06.135 [http-nio-8080-exec-1] [DEBUG] [o.s.s.web.DefaultRedirectStrategy] Redirecting to http://localhost:8080/login.html 2022-11-19T10:07:06.136 [http-nio-8080-exec-1] [DEBUG] [o.s.s.w.c.HttpSessionSecurityContextRepository] Did not store empty SecurityContext 2022-11-19T10:07:06.137 [http-nio-8080-exec-1] [DEBUG] [o.s.s.w.c.HttpSessionSecurityContextRepository] Did not store empty SecurityContext 2022-11-19T10:07:06.137 [http-nio-8080-exec-1] [DEBUG] [o.s.s.w.c.SecurityContextPersistenceFilter] Cleared SecurityContextHolder to complete request 2022-11-19T10:07:06.169 [http-nio-8080-exec-2] [DEBUG] [o.s.security.web.FilterChainProxy] Securing GET /login.html 2022-11-19T10:07:06.169 [http-nio-8080-exec-2] [DEBUG] [o.s.s.w.c.SecurityContextPersistenceFilter] Set SecurityContextHolder to empty SecurityContext 2022-11-19T10:07:06.170 [http-nio-8080-exec-2] [DEBUG] [o.s.s.w.a.AnonymousAuthenticationFilter] Set SecurityContextHolder to anonymous SecurityContext 2022-11-19T10:07:06.170 [http-nio-8080-exec-2] [DEBUG] [o.s.s.w.a.i.FilterSecurityInterceptor] Failed to authorize filter invocation [GET /login.html] with attributes [hasRole('ROLE_USER')] 2022-11-19T10:07:06.171 [http-nio-8080-exec-2] [DEBUG] [o.s.s.w.s.HttpSessionRequestCache] Saved request http://localhost:8080/login.html to session 2022-11-19T10:07:06.171 [http-nio-8080-exec-2] [DEBUG] [o.s.s.web.DefaultRedirectStrategy] Redirecting to http://localhost:8080/login.html ...
更新:未收到回复,是否需要补充更多信息?
问题原因与修复方案
核心问题
登录页面/login.html被Spring Security的权限规则拦截,未认证的匿名用户访问时,被要求必须拥有USER/ADMIN角色,因此触发重定向到登录页面,形成无限循环。从日志中可以看到关键信息:Failed to authorize filter invocation [GET /login.html] with attributes [hasRole('ROLE_USER')],直接说明/login.html的访问权限配置错误。
修复步骤
- 开放登录路径的匿名访问权限:在
authorizeRequests中,将/login*(包含登录页面和错误页面)的规则放在最前面,允许所有匿名用户访问:
@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.csrf().disable(); http .authorizeRequests() .antMatchers("/login*").permitAll() // 允许所有用户访问登录相关路径 .antMatchers("/edit/**", "/delete/**").hasRole("ADMIN") // ADMIN专属路径 .antMatchers("/", "/search", "/browse", "/recipes/**", "/tags/**").hasRole("USER") // USER可访问路径 .anyRequest().authenticated() .and() .formLogin() .loginPage("/login.html") .defaultSuccessUrl("/", true) .failureUrl("/login.html?error=true"); return http.build(); }
- 调整规则顺序:Spring Security的权限规则是从上到下匹配,匹配到即停止,所以必须将开放权限的规则放在最前面,再依次放置更严格的ADMIN、USER规则,避免覆盖或错误拦截。
额外优化建议
- 登录表单的action改为绝对路径
/login,避免页面路径变化导致提交地址错误 - 若后续开启CSRF保护,在Thymeleaf模板中使用
th:action="@{/login}",自动生成CSRF令牌确保表单提交合法
内容的提问来源于stack exchange,提问作者CraigFoote
相关产品推荐
相关产品推荐

