You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3 Webflux/Kotlin中仅禁用指定Webhook端点CSRF防护

Spring Boot 3 Webflux/Kotlin 仅对指定端点禁用CSRF防护

问题背景

在Spring Boot 3 Webflux/Kotlin应用中,需要仅对/app/webhook端点禁用CSRF防护,但遇到以下问题:

  • 无法使用.csrf { it.ignoringAntMatchers("/app/webhook") },该方法在当前版本中不存在
  • Spring默认会对所有非GET的修改型请求应用CSRF防护,导致外部提供商的Webhook调用被拦截
  • 最初尝试在csrf.requireCsrfProtectionMatcher中使用NegatedServerWebExchangeMatcher未生效

原有配置代码如下:

@Bean
fun configure(http: ServerHttpSecurity): SecurityWebFilterChain {
    // @formatter:off
    return http
        .authorizeExchange { it.pathMatchers(GET, *ALLOW_LIST_STATIC_RESOURCES).permitAll() }
        .authorizeExchange { it.pathMatchers(GET, *ALLOW_LIST_VIEWS).permitAll() }
        .authorizeExchange { it.pathMatchers(GET, *ALLOW_LIST_RESOURCES).permitAll() }
        .authorizeExchange { it.pathMatchers(POST, *ALLOW_LIST_API_POST).permitAll() }
        .authorizeExchange { it.pathMatchers(DELETE, *ALLOW_LIST_API_DELETE).permitAll() }
        .formLogin { it.disable() }
        .headers { headers -> headers.contentTypeOptions { } }
        .headers { headers -> headers.frameOptions { it.mode(XFrameOptionsServerHttpHeadersWriter.Mode.DENY) } }
        .headers { headers -> headers.xssProtection { it.disable() } }
        .headers { headers -> headers.permissionsPolicy { it.policy("accelerometer=(), ambient-light-sensor=(), autoplay=(), camera=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), interest-cohort=(), magnetometer=(), microphone=(), midi=(), payment=(), usb=(), vr=(), xr-spatial-tracking=()") } }
        .headers { headers -> headers.contentSecurityPolicy { it.policyDirectives(contentSecurityPolicy) } }
        .build()
    // @formatter:on
}

解决方法

方案1:自定义CSRF匹配规则

通过自定义requireCsrfProtectionMatcher,结合默认匹配器和否定匹配器实现对指定端点的CSRF禁用,配置后问题解决:

.csrf { csrf -> 
    csrf.requireCsrfProtectionMatcher(disabledUrlForCSRF()) 
}.build()

fun disabledUrlForCSRF(): AndServerWebExchangeMatcher = AndServerWebExchangeMatcher(
    CsrfWebFilter.DEFAULT_CSRF_MATCHER,
    NegatedServerWebExchangeMatcher(
        ServerWebExchangeMatchers.pathMatchers(POST, "/app/webhook")
    )
)

方案2:通过securityMatcher缩小安全规则范围

另一种可行的实现方式是通过securityMatcher指定安全规则不作用于目标端点,整理后的配置如下:

@Bean
fun configure(http: ServerHttpSecurity): SecurityWebFilterChain {
    // @formatter:off
    return http
        .securityMatcher(
            isNot(ServerWebExchangeMatchers.pathMatchers(POST,"/app/webhook"))
        )
        .authorizeExchange { it.pathMatchers(OPTIONS).permitAll() }
        .authorizeExchange { it.pathMatchers(POST, *ALLOW_LIST_API_POST).permitAll() }
        .authorizeExchange { it.pathMatchers(DELETE, *ALLOW_LIST_API_DELETE).permitAll() }
        .authorizeExchange { it.pathMatchers(GET).permitAll() }
        .authorizeExchange { it.anyExchange().denyAll() }
        .httpBasic { it.disable() }
        .formLogin { it.disable() }.securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
        .build()
    // @formatter:on
}

fun isNot(matcher: ServerWebExchangeMatcher): ServerWebExchangeMatcher {
    return NegatedServerWebExchangeMatcher(matcher)
}

注意事项

  • 启用CSRF时,即使配置了NoOpServerSecurityContextRepository,仍会生成SESSION cookie
  • 添加所有GET端点的permitAll()配置,可在用户访问不存在页面时重定向到自定义错误页

内容的提问来源于stack exchange,提问作者Shaunyl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 09:45:00