Spring Cloud Gateway开启CSRF后登录POST拦截及默认登录页问题
问题根因
你遇到的两个问题分别由配置缺失、配置写法错误导致:
- 默认登录页跳转问题:一是没有显式关闭Spring Security默认开启的表单登录、HTTP Basic认证能力,未认证请求访问受限路径时会自动触发默认登录页跳转;二是授权规则写法存在链式调用断裂问题,仅配置了
/login路径的放行规则,未配置其余路径的访问逻辑,导致非/login请求全被默认认证规则拦截。 - CSRF token缺失报错:WebFlux响应式环境下
CsrfToken是惰性加载的,仅配置CookieServerCsrfTokenRepository不会主动触发token写入响应Cookie,前端Angular拿不到XSRF-TOKENCookie,发起POST登录请求时无法携带X-XSRF-TOKEN请求头,自然触发CSRF校验失败。
解决方案
1. 补全正确的安全配置
首先修正SecurityWebFilterChain的链式写法,关闭不需要的默认认证能力,补全授权规则,同时新增一个WebFilter主动触发CSRF token写入Cookie,完整配置如下:
@Configuration @EnableWebFluxSecurity public class NettyConfiguration implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> { @Value("${server.max-initial-line-length:65536}") private int maxInitialLingLength; @Value("${server.max-http-header-size:65536}") private int maxHttpHeaderSize; @Override public void customize(NettyReactiveWebServerFactory container) { container.addServerCustomizers( httpServer -> httpServer.httpRequestDecoder( httpRequestDecoderSpec -> { httpRequestDecoderSpec.maxHeaderSize(maxHttpHeaderSize); httpRequestDecoderSpec.maxInitialLineLength(maxInitialLingLength); return httpRequestDecoderSpec; } ) ); } /** * 主动触发CSRF token加载,写入响应Cookie */ @Bean public WebFilter csrfCookieWebFilter() { return (exchange, chain) -> { exchange.getAttributeOrDefault(CsrfToken.class.getName(), Mono.empty()) .cast(CsrfToken.class) .subscribe(); return chain.filter(exchange); }; } @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { http // 关闭不需要的默认认证机制,避免跳默认登录页 .formLogin(ServerHttpSecurity.FormLoginSpec::disable) .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable) // 跨域场景开启,需提前配置CorsConfigurationSource .cors(Customizer.withDefaults()) .csrf(csrf -> csrf // 配置Cookie存储CSRF token,关闭HttpOnly允许前端JS读取 .csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse()) ) .authorizeExchange(exchanges -> exchanges // 放行所有OPTIONS预检请求,跨域场景必须 .pathMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 放行登录接口 .pathMatchers("/login").permitAll() // 其余路径根据业务需求配置,示例为需要认证,可自行调整 .anyExchange().authenticated() ); return http.build(); } }
2. 跨域场景额外配置
如果前端Angular服务和网关不同域,还需要做两处配置:
- 网关侧配置CORS规则:允许前端域名作为访问源、允许携带凭证、允许
X-XSRF-TOKEN请求头;同时给CookieServerCsrfTokenRepository配置Cookie的sameSite属性为None(HTTPS环境下)、domain为前后端共同的父域名,确保跨域场景下Cookie可正常写入。 - 前端Angular侧:发起HTTP请求时开启
withCredentials: true,允许跨域请求携带Cookie。Angular默认的HttpClient已经实现了自动读取XSRF-TOKENCookie、自动往非GET请求里加X-XSRF-TOKEN请求头的逻辑,不需要额外写拦截器处理。
注意事项
- 不要为了绕过CSRF校验把
/login路径加入CSRF白名单,会导致登录接口失去CSRF防护,存在安全风险。 - 确保前端加载时第一个发起的GET请求能正常触达网关,CSRF Cookie会在该请求的响应中被自动写入,后续业务请求会自动携带token完成校验。
内容的提问来源于stack exchange,提问作者manjosh
相关产品推荐
相关产品推荐

