我们的rails3应用程序与作为REST函数公开的另一个rails应用程序进行通信。在对REST服务进行的所有POST调用中,迁移到rails3后会收到以下警告。
WARNING: Can't verify CSRF token authenticity
当我们对REST服务进行POST调用时,我们应该如何在线路上传递csrf令牌,ApplicationController具有protect_from_forgery方法,并且该调用也会落在handle_unverified_request调用上。我们使用HTTP basic auth进行身份验证,它似乎工作正常。我们该怎么做才能解决这个问题。
答案 0 :(得分:11)
好的,现在我会试一试回答你的问题。
CSRF令牌是“会话相关的”,这意味着用户必须与正在与之通信的应用程序共享会话。这意味着必须在提交实际表单之前提出请求,这是标准HTML表单的情况,表单在提交之前显示,因此可以为该用户生成CSRF令牌。
让我们调用提供UI按钮App1的应用程序和托管REST服务App2的应用程序。
用户与App1共享会话并获取App1提供的UI按钮。一旦用户单击该按钮,就会向App1发出请求,App1向App2的REST服务发出请求。
结论:用户不与App2共享会话,但您的App1与App2会话。最后有两件事:
用户不容易受到App2上的跨站点伪造的影响,因为他在该服务器上没有会话。因此,如果我在这里发布类似<img src="http://app2.com/rest-service/destroy>
的内容,App2将无法识别我,因为我没有与App2共享会话而且没有任何反应。
您可以在REST服务上实施自己的安全措施,以保护它免受公众的侵害:
这意味着您可以在REST服务上删除CSRF保护并保持安全,只要用户无法通过AJAX等直接进行呼叫。
<强>加成强>
CSRF保护您的网站不受来自您的来源的提交表单(实际上这仅适用于POSTed表单,因为它们通常操纵数据。
最大的情况是:我是攻击者,我想将您的用户帐户名称更新为“Potatoe先生”,我的方式就是在我的网站上放置一个隐藏的表单,然后将其发布到Yourdomain.com/account
有一个隐藏字段account[name]="Mr. Potatoe"
。现在没有CSRF保护会发生什么?我的浏览器提交表单,并用它发送身份验证cookie,我的名字现在是“Potatoe先生”。 CSRF保护会发生什么?我的浏览器提交表单并发送cookie,但表单没有CSRF令牌,因此请求被拒绝。现在有没有办法让攻击者在这些情况下获得CSRF令牌?答案是不。也许你问自己......
如果我在我的网站上放置一个隐藏的iframe,指向Yourdomain.com/account/edit
并只复制包含该令牌的隐藏字段,该怎么办? - 答案:由于相同的原始政策,它无法正常工作,如果iframe的内容不是来自您的域名,则无法读取iframe内的内容。
如果我在后台进行AJAX调用以获取令牌怎么办?答:它不起作用,因为使用纯AJAX你也必须遵守相同的原始政策。
现在让我们谈谈:我无法从我的页面向您发送隐藏的AJAX调用,以伤害我网站上的用户。
这是什么意思?您可以实现一个前置过滤器,用于检查request.xhr?
是否为真,或者用户代理是否类似于“我的REST客户端XY”,因为这不能通过&gt;&gt;浏览器&lt;&gt;中的跨站点请求来伪造。 &LT ;.因此,如果是这种情况,您可以忽略/禁用CSRF保护。
顺便说一下,如果你想在你的站点中发出一个AJAX请求,你可以得到这样的CSRF令牌:
var token = $('meta[name="csrf-token"]').attr('content');
请参阅Rails UJS脚本:https://github.com/rails/jquery-ujs/blob/master/src/rails.js#L81
注意:这只能保护您免受跨站点伪造和其他任何行为....