如何在rails应用程序之间传递CSRF令牌

Sam*_*Sam 12 ruby-on-rails csrf ruby-on-rails-3

我们的rails3应用程序与作为REST函数公开的另一个rails应用程序对话 在对REST服务进行的所有POST调用中,迁移到rails3后会收到以下警告.

WARNING: Can't verify CSRF token authenticity
Run Code Online (Sandbox Code Playgroud)

当我们对REST服务进行POST调用时,我们应该如何在线路上传递csrf令牌,ApplicationController具有protect_from_forgery方法,并且该调用也落在handle_unverified_request调用上.我们使用HTTP basic auth进行身份验证,它似乎工作正常.我们该怎么做才能解决这个问题.

sle*_*led 11

好的,现在我会试一试回答你的问题.

CSRF令牌是"会话相关的",这意味着用户必须与正在与之通信的应用程序共享会话.这意味着必须在提交实际表单之前提出请求,这是标准HTML表单的情况,其中表单在提交之前显示,因此可以为该用户生成CSRF令牌.

让我们调用为UI按钮App1提供服务的应用程序和托管REST服务App2的应用程序.

用户与App1共享会话并获取App1提供的UI按钮.一旦用户单击该按钮,就会向App1发出请求,App1向App2的REST服务发出请求.

结论:用户不与App2共享会话,但您的App1与App2会话.这包括两件事:

  1. 用户不容易受到App2上的跨站点伪造的影响,因为他在该服务器上没有会话.因此,如果我发布类似这样的内容<img src="http://app2.com/rest-service/destroy>,App2将无法识别我,因为我没有与App2共享会话而且没有任何反应.

  2. 您可以在REST服务上实施自己的安全措施,以保护它免受公众攻击:

    • 通过HTTP Basic Auth进行身份验证
    • 通过API密钥进行身份验证
    • ....

这意味着只要用户无法通过AJAX等直接调用,您就可以在REST服务上删除CSRF保护并保持安全.

加成

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调用,以伤害我网站上的用户.

这是什么意思?您可以实现一个before过滤器,它检查是否request.xhr?为true或者用户代理是否类似于"我的REST客户端XY",因为这不能由>> browser <<中的跨站点请求伪造.因此,如果是这种情况,您可以忽略/禁用CSRF保护.

顺便说一下,如果你想在你的站点中发出一个AJAX请求,你可以得到这样的CSRF令牌:

var token = $('meta[name="csrf-token"]').attr('content');
Run Code Online (Sandbox Code Playgroud)

请参阅Rails UJS脚本:https://github.com/rails/jquery-ujs/blob/master/src/rails.js#L81

注意:这只能保护您免受跨站点伪造而无需其他任何操作....