如何使用Rails AuthenticityToken基础结构明确保护GET操作

时间:2009-12-04 17:41:21

标签: ruby-on-rails csrf authenticity-token

Rails AuthenticityToken自动保护来自CSRF攻击的POST / PUT / DELETE请求。但我还有另一个用例。

我在我的网站上显示一个视频,我不想在其他网站上嵌入。这是如何工作的,我的Flash播放器从我的CDN发送一个签名URL请求,该请求将在几秒钟后到期。到目前为止,用户必须登录才能观看视频,因此这是身份验证。但是现在我希望网站的任何访问者都能够观看视频而不允许从其他网站请求签名的网址(例如,如果他们将我们的播放器嵌入他们的网站)。

我的第一个想法是AuthenticityToken,因为它似乎具有这些确切的语义......我需要做的就是将其插入GET请求中。有什么想法吗?

2 个答案:

答案 0 :(得分:9)

Rails,自以为是认为所有GET请求都应该是幂等的。这意味着Rails当然不会检查GET请求的真实性令牌,甚至是verify_request?给每个GET一个通行证。

def verified_request?
  !protect_against_forgery?     ||
    request.method == :get      ||
    !verifiable_request_format? ||
    form_authenticity_token == params[request_forgery_protection_token]
end

所以我们必须编写自己的逻辑。我们可以使用form_authenticity令牌。所有这一切都是创建一个随机字符串并将其缓存在会话中:

def form_authenticity_token
   session[:_csrf_token] ||= ActiveSupport::SecureRandom.base64(32)
end

因此,我们可以创建一个前置过滤器,用于测试url参数与会话令牌的相等性。从而确保只有真正的游客可以观看视频。

控制器:

class CDNController < ActionController::Base
  # You probably only want to verify the show action
  before_filter :verify_request, :only => 'show'

  # Regular controller actions…

  protected

  def verify_request
    # Correct HTTP response code is 403 forbidden, not 404 not found.
    render(:status => 403) unless form_authenticity_token == params[:token]
  end

end

观点:

<%= video_path(:token => form_authenticity_token) %>

答案 1 :(得分:1)

在您的网址中插入真品令牌:

<%= video_path(:token => form_authenticity_token) %>

在您的CDN控制器中,您可以使用before_filter检查真实性标记是否正确:

def verify_token
    render_404 unless form_authenticity_token == params[:token]
end

def render_404
    render :file => "#{RAILS_ROOT}/public/404.html", :status => 404
end