CSRF 令牌不是使用 Webflux 生成的

2024-07-04

我有一个由 Spring Security 保护的 Webflux 应用程序,其中默认启用 CSRF 保护。但是,我无法将 CSRF 令牌保存在会话中。

经过一番调查,我注意到它可能来自WebSessionServerCsrfTokenRepository.class。在这个班级里,有generateToken应该从生成的 CSRF 令牌创建 Mono 的方法:

public Mono<CsrfToken> generateToken(ServerWebExchange exchange) {
        return Mono.fromCallable(() -> {
            return this.createCsrfToken();
        });
    }

private CsrfToken createCsrfToken() {
        return new DefaultCsrfToken(this.headerName, this.parameterName, this.createNewToken());
    }

    private String createNewToken() {
        return UUID.randomUUID().toString();
    }

然而,即使generateToken方法被调用CsrfWebFilter, the createCsrfToken方法从未被调用,并且我从未将 CSRF 令牌保存在会话中。我的断点永远不会进入createCsrfToken方法,这可能意味着它永远不会被订阅。

我正在奔跑Netty带有弹簧引导2.1.0.RELEASE和Spring安全5.1.1.RELEASE.

我在一个仅包含以下依赖项的空示例应用程序上重现了该问题:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-client</artifactId>
        </dependency>

我是否遗漏了什么或者 Spring Security 有问题?

UPDATE

经过进一步调查,我认为问题出在Spring Security中的这个方法上CsrfWebFilter.class:

private Mono<Void> continueFilterChain(ServerWebExchange exchange, WebFilterChain chain) {
        return Mono.defer(() -> {
            Mono<CsrfToken> csrfToken = this.csrfToken(exchange);
            exchange.getAttributes().put(CsrfToken.class.getName(), csrfToken);
            return chain.filter(exchange);
        });
    }

在这里,csrfTokenMono 永远不会被订阅。当我以这种方式重写过滤器时,我设法在会话中添加令牌:

private Mono<Void> continueFilterChain(ServerWebExchange exchange, WebFilterChain chain) {
        return Mono.defer(() -> {
            return this.csrfToken(exchange)
                    .map(csrfToken -> exchange.getAttributes().put(CsrfToken.class.getName(), csrfToken))
                    .then(chain.filter(exchange));
        });
    }

但是,那_csrf我的 Thymeleaf 模型中从未添加过参数,因此以下测试不起作用:

<form name="test-csrf" action="/test" method="post">
            <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
            <button type="submit">Escape!</button>
        </form>

如果有人遇到这个问题,我与 Spring 团队的某人进行了讨论。

它实际上并不打算订阅csrfTokenMono只在需要的时候直接做。开发人员有责任在应用程序中触发订阅,有两种方法可以实现。

方法一:显式订阅。

通过以下方式提供订阅@ModelAttribute在一些@ControllerAdvice或抽象控制器类:

@ModelAttribute(CsrfRequestDataValueProcessor.DEFAULT_CSRF_ATTR_NAME)
    public Mono<CsrfToken> getCsrfToken(final ServerWebExchange exchange) {

        return exchange.getAttributeOrDefault(CsrfToken.class.getName(), Mono.empty());
    }

方法2:使用Thymeleaf自动处理CSRF。

确保 POM 中有以下依赖项才能将 Thymeleaf 与 Spring Security 一起使用:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>

这将自动将 CSRF 令牌添加到您的模型中,并通过表单隐藏输入传递它(仍需要将其添加到 POST Ajax 请求的标头中)。

欲了解更多信息,这是我在 Spring 上提出的问题:https://github.com/spring-projects/spring-security/issues/6046 https://github.com/spring-projects/spring-security/issues/6046

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CSRF 令牌不是使用 Webflux 生成的 的相关文章

随机推荐

  • Jetpack Compose 更改滑块拇指尺寸

    有没有办法改变滑块拇指大小 我认为现在我们只能操纵颜色 var sliderPosition by remember mutableStateOf 0f Text text sliderPosition toString Slider va
  • VueJS/Typescript - 找不到模块“./components/Navigation”或其相应的类型声明

    当我创建一个脚本作为打字稿 lang ts 时 我收到一条错误消息 找不到模块 components Navigation 或其相应的类型声明 Vetur 2307 我意识到只有当我将 lang 设置为 ts 时才会发生这种情况 这是我构建
  • 在 Visual Studio 2010 Professional 下更改 C++ Windows 窗体应用程序的启动窗体

    由于某种原因 我似乎找不到一种方法来做到这一点 更改 Visual Studio Professional 2010 下 C Windows 应用程序的启动形式 正如许多网站建议的那样 进入 Project properties Appli
  • 在绘制之前停止 NSView drawRect 清除? (lockFocus 不再在 macOS 10.14 上运行)

    我有一个使用两个视图的动画 我将调用 lockFocus 并使用 NSGraphicsContext currentContext graphicsPort 获取第二个 NSView 的图形上下文 然后进行绘制 在 macOS 10 14
  • Neo4j 节点/关系不一致

    当获取或当我尝试删除特定节点时 例如 MATCH p where ID p 79259223 OPTIONAL MATCH p r drops p s relations DELETE r p 我收到以下错误 在加载节点 79259223
  • cmd 将“字符保存到文件中,不换行

    是否可以将特殊字符 保存到字符串中而无需换行 我尝试了下面的代码 但没有一个工作 echo set p gt gt C text txt echo set p gt gt C text txt echo set p gt gt C text
  • 导入错误:没有名为“appdirs”的模块

    我正在尝试获取一个名为环聊机器人 https github com hangoutsbot hangoutsbot在我的 Linux 服务器上工作 我目前正在使用数字海洋服务器 然而 每次我尝试运行该脚本时 它都会给出一个错误 Import
  • ASP.NET CheckBox 在回发时未选中,没有奇怪的黑客攻击

    我有一个GridView带有复选框列 单击按钮后 所有选中复选框的行都应被删除 我不知何故偶然发现了一个奇怪而老套的解决方案 但我不知道它为什么有效 我已经搜索过相关的SO问题了 相关代码 Protected Sub Page Init B
  • 如何重新连接到 slime/swank-clojure 会话?

    似乎每当我从 clojure slime 会话断开连接时 我就无法再次重新连接 我正在使用 leiningen 启动 swank 会话 使用 lein swank 插件 所以 每次我退出 emacs 我知道我不应该 或重新启动 注销时 我都
  • 如何在microsoft access中动态加载、访问和卸载子表单

    我正在尝试从 ASP NET 过渡到 Access 中的编程 并且当我想到 Access 中的子表单时 我习惯于从用户控件的角度进行思考 我想做的是允许用户单击按钮来加载包含用户可以输入附加数据的控件的子表单 如果有任何信息或资源能够帮助我
  • 为什么同一个lua脚本执行结果不一致?

    为什么同一个lua脚本执行结果不一致 你好 lua obj a haha b jiji c name tom age 15 for i v in pairs obj do if i c then print i v age v name b
  • 使用 jQuery Toggle 更改 div 文本

    使用时slideToggle 如何更改文本关闭 显示 我做了一个简单的操作 但无法恢复文本更改 这是我所做的 document ready function open click function showpanel slideToggle
  • 从 Mac 应用程序启动 Safari

    如何启动 Safari 浏览器或用户的默认浏览器 将其指向 Mac 应用程序中的特定地址 我使用 Objective C 作为编程语言 Thanks 从 shell 中您可以使用open命令以 URL 作为参数 并且负责在默认浏览器中打开该
  • 在 UIPageViewController 中,当“pageViewController:viewControllerBeforeViewController”被调用时?

    我尝试在中显示照片UIPageViewController 首先 我在集合视图中显示我的照片 然后点击一张照片进入页面视图 然而 当我在页面视图中时 如果我滚动当前照片 向右或向左 我发现两者pageViewController viewC
  • iPad ajax 问题

    长话短说 我必须创建一个聊天功能 该功能似乎适用于除 iPad 也可能是 iPhone 之外的所有设备 我们的客户使用他们的 iPad 进行聊天 因此我在过去 7 个月左右的时间里一直在尝试解决这些问题 这就是我花了多长时间才找出问题所在
  • 在 Codeigniter 中创建块/模块

    到目前为止 我一直很喜欢使用 CodeIgniter 创建一些简单的 Web 应用程序 实际上只是学习框架 但我无法找到创建块 模块的简单方法 我希望有一个 最近的图像 块 我可以将其放在网站上的任何页面上 而无需在每个页面的控制器中重复查
  • Resharper 在 Visual Studio 2010 中不断禁用“显示实时语义错误”

    如何防止 Resharper 禁用 Visual Studio 中的 显示实时语义错误 和 下划线错误 选项 似乎每当我手动启用它们时 它们都会在一段时间后以某种方式恢复为禁用状态 我怀疑 Resharper 这样做了 有什么补救办法吗 如
  • 域名注册如何进行? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我在谷歌和维基百科上搜索了很多 但我找不到这些问题的答案 1 注册公司具体做什么 他们更新根 DNS 并在那里设置我的 DNS 的 IP 2 注册商为
  • 实例化新视图控制器时从内存中删除视图控制器

    在我的应用程序中 我实例化新的视图控制器而不是使用 Segues 因为它在动画中看起来更好 因此我的视图继续在后台运行 这会导致大量内存泄漏 我返回主屏幕的代码是 let mainStoryboard UIStoryboard name M
  • CSRF 令牌不是使用 Webflux 生成的

    我有一个由 Spring Security 保护的 Webflux 应用程序 其中默认启用 CSRF 保护 但是 我无法将 CSRF 令牌保存在会话中 经过一番调查 我注意到它可能来自WebSessionServerCsrfTokenRep