【问题标题】:Why are csrf token's usually stored in hidden form fields?为什么 csrf 令牌通常存储在隐藏的表单字段中?
【发布时间】:2020-10-21 04:46:52
【问题描述】:

我正在开发一个 React 应用程序,并且正在考虑实施一种 CSRF 缓解技术。我决定使用 Same-Site cookie,但在此之前,我正在研究使用 CSRF 令牌并阅读了许多帖子,说它们应该存储在隐藏的表单字段中。我想知道的是,将其存储在隐藏字段中和将其存储在类变量之类的东西中是否有区别?如果它的目的是在您准备好向服务器发送请求时保存在某个地方,那么它在客户端的存储方式是否重要?

【问题讨论】:

    标签: javascript reactjs security csrf


    【解决方案1】:

    其他答案是正确的,因为对于您在某处找到的教程(或 csrf 上的通用教程),使用在表单字段中编写的令牌更容易演示它,传统的 Web 应用程序也可以这样工作。

    其他人没有提到的是像 React 这样的现代单页应用程序不能那样工作,通常你甚至没有表单,并且将令牌写入表单字段是没有意义的。所以这些应用程序通常不会这样做。

    这还有一个实际的方面。您提到将其存储在类变量中。这很好,但它如何到达那里?令牌通常(不一定,但现在这是一个支线)由服务器端 Web 应用程序生成。 javascript SPA 将如何获得它?您需要将它写在页面中的某处,花费单独的请求来获取它会浪费资源。通常发生的一件事是将其写入页面顶部的元标题(例如<meta name="csrf" content="...">),以便您的 SPA 可以从那里读取它并将其存储在任何需要的位置。

    另外一件经常发生的事情是甚至不需要 csrf 保护,因为 api 认证是基于请求头之类的东西(而不是 cookie 中的东西),它不会被浏览器自动发送,所以经典的 csrf 不是可行。

    【讨论】:

    • http 请求的响应正文是 html 的页面本身。我们正在讨论在页面中的位置。 :) 在 JSON 响应的情况下,您通常不需要明确的 csrf 保护,因为只有在浏览器自动发送身份验证信息(例如 cookie 中的 sessionid)时才能利用 CSRF。如果您的应用程序将 JWT 作为请求标头(例如授权)发送,则 CSRF 不能被利用,但 Http Basic auth 除外,如果用户输入,它持久化并自动发送,因此需要保护csrf.
    • 您需要以某种方式对请求进行身份验证,因为您将发送某种令牌。如果那是标头中的 jwt,则不需要单独的 csrf 保护。如果它是 cookie 中的会话 id 或 jwt(或自动发送的任何内容),则您需要不会自动发送的 csrf 保护。所以为了防止 csrf,你需要 something 不是自动的。要对请求进行身份验证,您需要适合该请求的东西,它可能(例如 Authorization 标头中的 jwt)也可能不会(例如会话 cookie)固有地防止 csrf。
    • 另外请注意,使用 httponly cookie 来存储身份验证信息(会话 id 或 jwt)比其他任何东西都更安全,因为它受到 xss 的保护。如果你有一个基于 cookie 的解决方案,你应该实现单独的 csrf 保护,而不是将身份验证更改为基于令牌/标头。
    • 感谢您清晰的解释。出于这个原因,我通常只将 jwt 存储在 httponly cookie 中。这就是为什么我没有考虑在标头中发送它的原因,因为我知道 javascript 将无法访问它。在这种情况下,现在实现 csrf 令牌是有意义的,对吧?
    • 在这种情况下,您需要保护您的应用程序免受 csrf 的影响,是的。
    【解决方案2】:

    CSRF 令牌存储在隐藏输入中的原因是,当提交表单时它会自动发送到服务器。如果您手动向服务器发送请求并自己获取数据,则可以将 CSRF 存储在任何地方。最好保持一致并将其存储在隐藏的输入中。

    【讨论】:

    • 这是有道理的。所以这样做更方便。但是如果你没有表格怎么办?假设您只有一个按钮,当您单击它时,它对数据库进行了某种更改,但不一定对表单进行任何输入。那么将 CSRF 存储在其他地方会更合适吗?
    • 即使没有完整的表单,我仍然会使用隐藏输入并以编程方式从输入中获取值。如果您不想这样做,我会将其存储为数据属性。我只是不会将它存储为一个类。
    • 所以你建议在页面某处隐藏输入元素,不管它是否是表单的一部分?我没有考虑在表单之外存在输入,但没有理由不能这样做
    【解决方案3】:

    如果您将它放在表单字段中,那么通常一切都可以正常工作,但是如果您将值放在其他任何地方,那么您必须编写逻辑来提取该值并将其插入回发送到服务器的表单数据中.

    使用表单字段也适用于 ajax 和标准表单提交,因此大多数教程将推广它而不是仅适用于其中一个或另一个的方法。

    【讨论】:

    • 如果您发送到服务器的数据不是来自表单怎么办?这里我使用表单数据意味着它是从表单元素中获取的数据。但是,如果您只有一个按钮之类的东西,当您单击该按钮时,会对数据库进行一些更改呢?所以不一定有一个表单可以接受任何输入。
    猜你喜欢
    • 2015-04-14
    • 1970-01-01
    • 2013-06-04
    • 2019-07-20
    • 2020-06-11
    • 1970-01-01
    • 2019-04-28
    • 2012-04-13
    • 1970-01-01
    相关资源
    最近更新 更多