4

Rails AuthenticityToken 自动保护 POST/PUT/DELETE 请求免受 CSRF 攻击。但我想到了另一个用例。

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

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

4

2 回答 2

9

Rails 固执己见,认为所有 GET 请求都应该是幂等的。这意味着 Rails 当然不会检查 GET 请求的真实性令牌,甚至是验证请求?给每个 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

因此,我们可以创建一个 before 过滤器来测试 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) %>
于 2009-12-05T02:52:33.713 回答
1

要将真实性令牌插入您的 url:

<%= 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
于 2009-12-04T23:59:28.123 回答