Spring自定义登录页始终标记用户为匿名,提交后报403错误
排查Spring Security自定义JSP登录页提交后403 Forbidden问题
结合你描述的情况——用默认登录页能正常登录,换自定义页就出403,而且用户权限没问题,大概率是自定义登录页的表单配置或者Spring Security的CSRF防护没处理到位,咱们一步步来排查:
1. 优先检查CSRF令牌是否正确添加
Spring Security默认开启CSRF防护,自定义登录表单必须携带CSRF令牌,否则提交请求会被直接拦截返回403。这是最常见的原因!
你需要在JSP登录表单里添加这个隐藏字段:
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
完整的表单示例大概是这样:
<form action="${pageContext.request.contextPath}/login" method="post"> <div> <label>用户名:<input type="text" name="username"></label> </div> <div> <label>密码:<input type="password" name="password"></label> </div> <!-- 必须包含的CSRF令牌 --> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> <button type="submit">登录</button> </form>
2. 核对表单的关键配置
- 提交方式:必须是
POST,Spring Security的登录处理接口只接受POST请求,用GET会直接拦截。 - action路径:要和Spring Security配置里的
loginProcessingUrl完全一致。比如你配置的是/login,那表单action就得写${pageContext.request.contextPath}/login(带上项目上下文路径,避免路径错误)。 - 字段名称:用户名和密码的input标签
name属性,默认必须是username和password。如果你在Spring Security里自定义了参数名,要确保和配置里的usernameParameter、passwordParameter对应。
3. 检查Spring Security配置类
- 确认登录页本身被放行:配置里要加上
requestMatchers("/login").permitAll(),确保未登录用户能访问登录页(你能打开登录页的话这个大概率没问题,但还是确认下)。 - 确认登录处理路径未被拦截:
loginProcessingUrl对应的路径(比如/login)Spring Security会自动放行,但如果你的配置里有其他自定义拦截规则,要确保没有覆盖这个放行逻辑。
示例配置类(Java配置):
@Configuration @EnableWebSecurity public class SecurityConfig { @Autowired private UserDetailsService userDetailsService; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers("/login", "/static/**").permitAll() // 放行登录页和静态资源 .anyRequest().authenticated() ) .formLogin(form -> form .loginPage("/login") // 指定自定义登录页的访问路径 .loginProcessingUrl("/login") // 登录请求的处理路径,和表单action一致 .defaultSuccessUrl("/home", true) // 登录成功后跳转的页面 .failureUrl("/login?error") // 登录失败后跳转回登录页并携带错误标识 ); return http.build(); } }
4. 查看详细日志定位问题
你提供的日志片段不够完整,建议把org.springframework.security的日志级别改成DEBUG,这样能看到具体是哪个过滤器拦截了请求:
- 如果是
CsrfFilter拦截,那就是CSRF令牌的问题; - 如果是
AuthorizationFilter拦截,那可能是权限配置的问题,但结合默认登录页能正常登录,这种情况概率很低。
按照上面的步骤排查,应该就能解决403的问题了。
内容的提问来源于stack exchange,提问作者Tocka Ayman
相关产品推荐
相关产品推荐

