如何使用 Rails AuthenticityToken 基础设施显式保护 GET 操作

发布于 2024-08-13 17:10:28 字数 335 浏览 8 评论 0原文

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

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

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

Rails AuthenticityToken automatically protects POST/PUT/DELETE requests from CSRF attacks. But I have another use case in mind.

I am showing a video on my site that I don't want to be embeddable on other sites. How this works is that my flash player sends a request for a signed URL from my CDN that expires in a few seconds. Up until now a user had to be logged in to watch videos, so that was the authentication. However now I want any visitor to the site to be able to watch the video without allowing the signed URL to be requested from another site (such as if they embedded our player on their site).

My first thought went to AuthenticityToken since it seems to have these exact semantics... all I need to do is plug it into a GET request. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

新人笑 2024-08-20 17:10:28

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

因此,我们可以创建一个 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) %>

Rails, opinionated as it is believes that all GET requests should be idempotent. This means Rails of course does not check authenticity tokens for GET requests, even verified_request? gives every GET a pass.

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

So we have to write our own logic. We can use form_authenticity token. All this does is create a random string and cache it in the session:

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

We can therefore make a before filter that tests the equality of a url parameter to the session token. Thereby ensuring that only bonafide visitors can view videos.

Controller:

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

The view:

<%= video_path(:token => form_authenticity_token) %>
我的黑色迷你裙 2024-08-20 17:10:28

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

<%= 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

To plug the authenticity token in your url:

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

In your CDN's controller, you could check if the authenticity token is correct with a 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文