Spring Security访问出现页面重定向异常及403权限问题排查
问题分析与解决方案
1. 根路径无限重定向问题
你设置了anyRequest().authenticated(),所有未匹配前置规则的请求都需要认证。访问http://localhost:8080时,会触发认证要求,Spring Security会重定向到你指定的自定义登录页/login。但你没有编写处理/login请求的Controller方法,导致访问/login返回404,Spring Security会再次将未认证请求重定向到/login,形成无限循环。
解决办法二选一:
- 方法一:实现自定义登录页Controller
添加Controller类处理/login的GET请求,返回登录页面(示例用Thymeleaf模板):@Controller public class LoginController { @GetMapping("/login") public String loginPage() { return "login"; // 对应resources/templates/login.html } } - 方法二:使用Spring Security默认登录页
去掉自定义登录页配置,改用默认登录页:.formLogin(form -> form.permitAll())
另外,建议显式将登录相关路径加入允许列表,避免拦截异常:
在authorizeHttpRequests中添加:
.requestMatchers("/login", "/login/**").permitAll()
2. /product/welcome返回403问题
你的规则顺序是正确的(先匹配/product/welcome允许匿名,再匹配/product/**要求ADMIN角色),出现403的可能原因:
- 请求路径不匹配:检查Controller中
/product/welcome的路径是否完全一致(比如是否多了斜杠),或请求方法是否对应(比如Controller是POST,你用GET访问)。 - 多Security配置冲突:确保项目中只有一个
SecurityFilterChainBean生效,避免规则覆盖。 - 缓存干扰:重启应用,清除浏览器缓存和Cookie,避免旧认证信息影响。
如果以上都没问题,可显式指定请求方法强化规则:
.requestMatchers(HttpMethod.GET, "/product/welcome").permitAll()
修改后的完整SecurityConfig示例
package com.cde.backend.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.factory.PasswordEncoderFactories; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity @EnableMethodSecurity public class SecurityConfig { @Bean public UserDetailsService userDetailsService(PasswordEncoder encoder) { UserDetails admin = User.withUsername("Alice") .password(encoder.encode("Pwd1")) .roles("ADMIN") .build(); UserDetails user = User.withUsername("John") .password(encoder.encode("Pwd2")) .roles("USER","ADMIN","HR") .build(); return new InMemoryUserDetailsManager(admin, user); } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { return http .csrf(csrf -> csrf.disable()) .formLogin(form -> form.permitAll()) // 使用默认登录页,或替换为自定义loginPage并添加对应Controller .authorizeHttpRequests(auth -> auth .requestMatchers("/product/welcome").permitAll() .requestMatchers("/product/**").hasRole("ADMIN") .requestMatchers("/login", "/login/**").permitAll() .anyRequest().authenticated() ).build(); } @Bean public PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } }
内容的提问来源于stack exchange,提问作者Tejas Sharma
相关产品推荐
相关产品推荐

