什么是Rails中的真实性令牌?


当前回答

Beware the Authenticity Token mechanism can result in race conditions if you have multiple, concurrent requests from the same client. In this situation your server can generate multiple authenticity tokens when there should only be one, and the client receiving the earlier token in a form will fail on it's next request because the session cookie token has been overwritten. There is a write up on this problem and a not entirely trivial solution here: http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/

其他回答

真实性令牌的设计使您知道您的表单是从您的网站提交的。它是由运行它的机器生成的,具有唯一的标识符,只有您的机器知道,因此有助于防止跨站请求伪造攻击。

如果您只是在rails拒绝AJAX脚本访问方面遇到困难,那么您可以使用

<%= form_authenticity_token %>

在创建表单时生成正确的令牌。

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

Beware the Authenticity Token mechanism can result in race conditions if you have multiple, concurrent requests from the same client. In this situation your server can generate multiple authenticity tokens when there should only be one, and the client receiving the earlier token in a form will fail on it's next request because the session cookie token has been overwritten. There is a write up on this problem and a not entirely trivial solution here: http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/

需要authenticity_token的方法

在post, put和delete等幂等方法的情况下需要authenticity_token,因为幂等方法对数据有影响。

为什么需要它

它需要防止邪恶的行为。Authenticity_token存储在会话中,每当在web页面上创建用于创建或更新资源的表单时,真实性令牌存储在隐藏字段中,并与服务器上的表单一起发送。在执行操作之前,用户发送的authenticity_token将与存储在会话中的authenticity_token进行交叉检查。如果authenticity_token相同,则进程继续,否则不执行操作。

真实性令牌是rails防止“跨站请求伪造(CSRF或XSRF)攻击”的方法。

简单地说,它确保对web应用程序的put / POST / DELETE(可以修改内容的方法)请求是由客户端浏览器发出的,而不是来自第三方(攻击者),后者有权访问在客户端创建的cookie。

会发生什么

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

为什么会这样

Since the authenticity token is stored in the session, the client cannot know its value. This prevents people from submitting forms to a Rails app without viewing the form within that app itself. Imagine that you are using service A, you logged into the service and everything is OK. Now imagine that you went to use service B, and you saw a picture you like, and pressed on the picture to view a larger size of it. Now, if some evil code was there at service B, it might send a request to service A (which you are logged into), and ask to delete your account, by sending a request to http://serviceA.example/close_account. This is what is known as CSRF (Cross Site Request Forgery).

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

API文档描述了元标签的细节:

使用protect_from_forgery方法开启CSRF保护, 它检查令牌并重置会话,如果它不匹配什么 是预期。为新的Rails生成对该方法的调用 默认应用程序。 token参数默认命名为authenticity_token。这个名字 并且这个标记的值必须添加到渲染的每个布局中 通过在HTML头中包含csrf_meta_tags来创建表单。

笔记

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

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

教训

使用authenticity_token来保护你的非幂等方法(POST、PUT/PATCH和DELETE)。还要确保不允许任何可能修改服务器上资源的GET请求。


检查@erturne关于GET请求是幂等的评论。他的解释比我在这里做的更好。