Spring Boot中Fetch提交/policy-holder端点重定向登录页问题排查
问题分析与解决方案
一、/policy-holder端点permitAll仍重定向到登录页的问题
原因
Spring Security默认开启CSRF保护,对于POST、PUT等非GET请求,即便配置了permitAll(),也需要携带有效的CSRF Token才能通过校验。你的前端Fetch请求未携带CSRF Token,导致请求被拦截,触发重定向到登录页的默认行为。
另外需确认端点路径匹配:Controller是@PostMapping("/policy-holder"),Security配置里的requestMatchers("/policy-holder")匹配所有HTTP方法,路径匹配无问题,核心问题仍为CSRF拦截。
解决步骤
前端请求添加CSRF Token
从页面Cookie中获取Spring Security默认存储的XSRF-TOKEN,在Fetch请求headers中添加X-XSRF-TOKEN字段:// 从Cookie提取CSRF Token function getCsrfToken() { const value = `; ${document.cookie}`; const parts = value.split(`; XSRF-TOKEN=`); if (parts.length === 2) return parts.pop().split(';').shift(); } fetch('/policy-holder', { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json', 'X-XSRF-TOKEN': getCsrfToken() }, body: JSON.stringify(extractedData), }) .then(response => response.json()) .then(data => console.log('POST请求响应:', data)) .catch(error => console.error('请求出错:', error));(可选)忽略该端点的CSRF检查
若该端点为公开API且无需CSRF保护,可在Security配置中添加忽略规则:@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf .ignoringRequestMatchers("/policy-holder") ) .authorizeHttpRequests((authorize) -> authorize.requestMatchers("/register/**","/css/**","/js/**", "/images/**").permitAll() .requestMatchers("/", "/index", "/policy-holder").permitAll() .requestMatchers("/users","/send").hasRole("ADMIN") .anyRequest().authenticated() ) .formLogin(form -> form .loginPage("/login") .loginProcessingUrl("/login") .defaultSuccessUrl("/users") .permitAll() ) .logout(logout -> logout .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .permitAll() ); return http.build(); }
二、Basic Auth与Cookie Auth(Form Login)共存的问题
原因
Spring Security默认不会同时启用Form Login和Basic Auth,需显式配置两者,并处理认证过滤器优先级,避免逻辑冲突。
解决步骤
在Security配置中同时启用formLogin()和httpBasic(),可按需设置Basic Auth的Realm信息:
@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf .ignoringRequestMatchers("/policy-holder") ) .authorizeHttpRequests((authorize) -> authorize.requestMatchers("/register/**","/css/**","/js/**", "/images/**").permitAll() .requestMatchers("/", "/index", "/policy-holder").permitAll() .requestMatchers("/users","/send").hasRole("ADMIN") .anyRequest().authenticated() ) .formLogin(form -> form .loginPage("/login") .loginProcessingUrl("/login") .defaultSuccessUrl("/users") .permitAll() ) .httpBasic(basic -> basic .realmName("ApplicationRealm") ) .logout(logout -> logout .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .permitAll() ); return http.build(); }
注意事项
- 两种认证方式可独立使用:
- Cookie Auth:登录后携带Session Cookie,请求保持
credentials: 'include'即可。 - Basic Auth:在请求headers中添加
Authorization: Basic <base64编码的用户名:密码>。
- Cookie Auth:登录后携带Session Cookie,请求保持
- 若需细分端点认证方式,可通过
requestMatchers()结合自定义过滤器或认证管理器实现。
内容的提问来源于stack exchange,提问作者uhexos
相关产品推荐
相关产品推荐

