当前位置: 首页 > 知识库问答 >
问题:

Spring(Spring Boot)如何向前端提供CSRF令牌?

范彭亮
2023-03-14

我正在尝试将CSRF保护添加到基于Spring-Boot(尤其是WebFlux)的项目中。

到目前为止,我所尝试的是低于安全配置。

@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {

    http.
        ...
        .and()
        .csrf()
        .csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse())
        .requireCsrfProtectionMatcher(
            new NegatedServerWebExchangeMatcher(
                new OrServerWebExchangeMatcher(
                    Arrays.asList(
                        ServerWebExchangeMatchers.pathMatchers(HttpMethod.POST, FORM_LOGIN_URL),
                        ServerWebExchangeMatchers
                            .pathMatchers(HttpMethod.GET, PERMISSION_ENDPOINT)
                    )
                )
            )
        )
        .accessDeniedHandler(new CustomHttpStatusServerAccessDeniedHandler(HttpStatus.FORBIDDEN))
        ...;

    return http.build();
}

但当我尝试上述配置时,我看不到任何与CSRF令牌从服务器推送到浏览器相关的内容。它不是默认推送到客户端吗?如果是这样的话,向客户端(浏览器)提供CSRF令牌的更干净的方法是什么?其中spring文档提到了这一点。(我跟着这个-

P、 S.(希望以下信息对回答有用)

  • Spring Boot Webflux应用程序未提供我的登录表单。它由运行在不同域(不同IP)上的角度应用程序提供服务

共有1个答案

督灿
2023-03-14

这一部分的文档记录有点糟糕,但显然,除非您订阅结果,否则不会保存csrf令牌。

@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {

   final CookieServerCsrfTokenRepository cookieServerCsrfTokenRepository = new CookieServerCsrfTokenRepository();
        cookieServerCsrfTokenRepository.setCookieHttpOnly(false);

    http.csrf()
            .csrfTokenRepository(cookieServerCsrfTokenRepository)
            .and()
            .cors()

             ...
}

// Add a tiny webfilter that just subscribes
@Bean
public WebFilter addCsrfToken() {
    return (exchange, next) -> exchange.<Mono<CsrfToken>>getAttribute(CsrfToken.class.getName())
                .doOnSuccess(token -> {}) // do nothing, just subscribe :/
                .then(next.filter(exchange));
}

如果您使用的是功能endpoint,则上述解决方案效果良好。您还可以使用ControllerAdvice方法。

@ControllerAdvice
public class SecurityControllerAdvice {@ModelAttribute Mono<CsrfToken> csrfToken(ServerWebExchange exchange) {
        Mono<CsrfToken> csrfToken = exchange.getAttribute(CsrfToken.class.getName());
        return csrfToken.doOnSuccess(token -> exchange.getAttributes()
                .put(CsrfRequestDataValueProcessor.DEFAULT_CSRF_ATTR_NAME, token));
    }
}

github上有一个开放的bug报告

CookieServerCsrfTokenRepository未添加cookie

 类似资料:
  • 如果HTTP POST返回一个HTTP 403禁止,但对HTTP GET有效,那么问题很可能与CSRF有关。提供CSRF令牌或禁用CSRF保护(不推荐)。 那么,a怎么能做到这一点呢?

  • 我的项目使用Spring Security 3.2.0.RC2,我的JSP使用Spring TagLib的form:form标记自动将CSRF令牌插入到我的表单中。 升级到Spring Security 3.2.0.版本后,我发现form:form标记不再自动将CSRF令牌插入到我的表单中,我现在必须通过将该令牌放在我的表单中来手动添加它: 还有其他人遇到过同样的问题吗?如果是,你做了什么工作?谢

  • 我在Spring框架中有csrf保护。所以在每个请求中,我都从ajax调用中发送csrf令牌,这是完美的工作。 在ajax

  • 我使用的是Spring Boot 2.1.1。我认为这个版本的Spring Boot默认启用了CSRF保护(如果我错了请纠正我)。我试图为我的java web应用程序设置CSRF保护,但我不确定需要做什么更改才能显示CSRF令牌。 我正试图通过浏览器检查CSRF令牌。但是,标记的名称和值似乎显示为空白。

  • 我已经用Spring Security保护了Spring Boot应用程序的APIendpoint。 登录时,我生成一个新的jwt令牌并将其提交给用户。 对于数据请求,我希望用户在头中提交令牌。 如果我这样做使用邮递员,它的工作完美罚款。当我试图用React发送令牌时,它失败了(axios/finch/超级代理)。问题不在于令牌本身的提交,因为如果我禁用授权,我可以用控制器读取授权头。 相反,Sp

  • 到目前为止,我只处理了服务器呈现的应用程序,在用户通过用户名/密码或使用OAuth提供商(Facebook等)登录后,服务器只是设置一个会话cookie,同时重定向到相关页面。 然而,现在我正在尝试使用更“现代”的方法构建一个应用程序,前端是React,后端是JSON API。显然,这方面的标准选择是使用JSON web令牌进行身份验证,但我很难弄清楚我应该如何将JWT提供给客户机,以便将其存储在