了解Rails真实性令牌

我遇到了一些关于Rails中真实性令牌的问题,因为我现在已经有很多次了。

但我真的不想解决这个问题,继续下去。 我真的很想了解真实性标记。 那么,我的问题是,你有这方面的一些完整的信息来源,或者你会花时间在这里详细解释吗?


怎么了

当用户查看表单以创建,更新或销毁资源时,Rails应用程序会创建一个随机authenticity_token ,将该令牌存储在会话中,并将其放置在表单中的隐藏字段中。 当用户提交表单时,Rails会查找authenticity_token ,并将其与存储在会话中的值进行比较,如果匹配,则允许继续此请求。

为什么会发生

由于真实性标记存储在会话中,客户端无法知道其值。 这可以防止人们在未查看该应用程序本身内的表单的情况下将表单提交给Rails应用程序。 想象一下,你正在使用服务A,你登录到服务,一切都很好。 现在想象一下,您使用了服务B,并且您看到了一张您喜欢的图片,并按下了图片以查看它的更大尺寸。 现在,如果服务B中存在一些恶意代码,它可能会向服务A(您登录的服务)发送请求,并通过向http://serviceA.com/close_account发送请求来要求删除您的帐户。 这就是所谓的CSRF(跨站点请求伪造)。

如果服务A使用真实性令牌,则此攻击向量不再适用,因为来自服务B的请求不包含正确的真实性令牌,并且将不被允许继续。

API文档描述了有关元标记的详细信息:

使用protect_from_forgery方法打开CSRF保护,该方法检查令牌,并在会话不符合预期时重置该会话。 默认情况下会为新的Rails应用程序生成对此方法的调用。 token参数默认命名为authenticity_token 。 通过在HTML头中包含csrf_meta_tags ,此标记的名称和值必须添加到呈现表单的每个布局。

笔记

请记住,Rails只验证不是幂等方法(POST,PUT / PATCH和DELETE)。 GET请求不被检查真实性标记。 为什么? 因为GET请求的HTTP规范状态是幂等,并在服务器应该创建,改变或破坏资源,应该将请求幂等(如果您运行相同的命令多次,你应该每次都得到相同的结果)。

同样,真正的实现在开始时定义更复杂一些,以确保更好的安全性。 Rails不会为每个表单发布相同的存储令牌。 它也不会每次生成和存储不同的标记。 它会在会话中生成并存储加密散列,并在每次呈现页面时发布新的加密令牌,这些令牌可以与存储的令牌相匹配。 请参阅request_forgery_protection.rb。

教训

使用authenticity_token保护您的非幂等方法(POST,PUT / PATCH和DELETE)。 另外请确保不允许任何可能会修改服务器资源的GET请求。


编辑:检查@erturne关于GET请求是幂等的评论。 他用比我在这里做的更好的方式解释它。


真实性标记旨在让您知道您的表单正在从您的网站提交。 它是从它所运行的机器生成的,它具有唯一的标识符,只有您的机器才能知道,因此有助于防止跨站点请求伪造攻击。

如果您在使用rails拒绝您的AJAX脚本访问时遇到困难,则可以使用

<%= form_authenticity_token %>

在创建表单时生成正确的标记。

您可以在文档中阅读更多关于它的信息。


什么是CSRF?

真实性令牌是跨站点请求伪造(CSRF)的一种对策。 你问什么是CSRF?

这是一种攻击者可能会在不知道会话令牌的情况下劫持会话的方式。

场景

  • 访问您的银行网站,登录。
  • 然后访问攻击者的网站(例如,来自不受信任的组织的赞助广告)。
  • 攻击者的页面包含与银行“转账资金”表单相同字段的表单。
  • 攻击者知道你的账户信息,并且已经预先填写了表单域来将钱从你的账户转移到攻击者的账户。
  • 攻击者的页面包括向您的银行提交表单的Javascript。
  • 表单提交后,浏览器会包含您的银行网站Cookie,包括会话令牌。
  • 银行将资金转移到攻击者的账户。
  • 该表单可以位于不可见的iframe中,因此您永远不会知道发生了攻击。
  • 这被称为跨站点请求伪造(CSRF)。
  • CSRF解决方案

  • 服务器可以标记来自服务器本身的表单
  • 每个表单必须包含一个额外的身份验证令牌作为隐藏字段。
  • 令牌必须是不可预知的(攻击者无法猜测它)。
  • 服务器在页面的表单中提供有效的令牌。
  • 服务器在发布表单时检查标记,拒绝没有正确标记的表单。
  • 令牌示例:使用服务器密钥加密的会话标识符。
  • Rails自动生成这样的标记:请参阅每种形式的authenticity_token输入字段。
  • 链接地址: http://www.djcxy.com/p/25803.html

    上一篇: Understanding the Rails Authenticity Token

    下一篇: Ruby: How to check whether a string isn't blank?