如何在 Rails 4 中覆盖控制器或动作的 X-Frame-Options

Posted

技术标签:

【中文标题】如何在 Rails 4 中覆盖控制器或动作的 X-Frame-Options【英文标题】:How to override X-Frame-Options for a controller or action in Rails 4 【发布时间】:2013-08-29 00:58:16 【问题描述】:

Rails 4 似乎为X-Frame-Options HTTP 响应标头设置了默认值SAMEORIGIN。这对于安全性而言非常棒,但它不允许您的应用的某些部分在不同域的iframe 中可用。

您可以使用config.action_dispatch.default_headers 设置全局覆盖X-Frame-Options 的值:

config.action_dispatch.default_headers['X-Frame-Options'] = "ALLOW-FROM https://apps.facebook.com"

但是如何为单个控制器或动作覆盖它?

【问题讨论】:

【参考方案1】:

上面的答案确实帮助了我,但在 2021 年使用 Rails 4.2 应用程序时,我需要关闭 X-Frame-Options 并仅为几个 URL 指定 Content-Security-Policy。

具体来说,我使用 2checkout 作为支付提供商,他们在 iframe 中打开了一些 URL....

我就是这样做的

class HomeController < ApplicationController
    after_action :allow_2checkout_iframe, only: [:privacy, :terms_of_service]

    def privacy
    end

    def terms_of_service
    end

    private
        def allow_2checkout_iframe
            response.headers.except! 'X-Frame-Options'
            response.headers['Content-Security-Policy'] = "frame-ancestors 'self' https://secure.2checkout.com"
        end
end

【讨论】:

【参考方案2】:

对于 Rails 5+,请改用 response.set_header('X-Frame-Options', 'ALLOW-FROM https://apps.facebook.com')。或者如果ALLOW-FROM 不起作用并且您需要快速修复,您可以将其设置为ALLOWALL

【讨论】:

这两个选项(ALLOW-FROM 和 ALLOWALL)都不再有效:developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…【参考方案3】:

我只是想在此处为任何发现此链接的人提供一个更新的答案,以便在尝试弄清楚如何让您的 Rails 应用程序嵌入 I-Frame 并遇到问题时。

截至 2020 年 5 月 28 日撰写本文时,X-Frame-Options 更改可能不是您解决问题的最佳方法。 “ALLOW-FROM”选项已被所有主流浏览器完全禁止。

现代解决方案是实施 Content-Security-Policy 并设置“frame_ancestors”策略。 'frame_ancestors' 键指定哪些域可以将您的应用程序嵌入为 iframe。它目前受主要浏览器支持并覆盖您的 X-Frame-Options。这将允许您防止点击劫持(X-Frame-Options 最初旨在帮助它在很大程度上被弃用)并在现代环境中锁定您的应用程序。

您可以在初始化程序中使用 Rails 5.2 设置 Content-Security-Policy(示例如下),对于 Rails https://github.com/github/secure_headers

如果您愿意,您还可以基于控制器/操作覆盖政策规范。

Content-Security-Policies 非常适合高级安全保护。查看您可以在 Rails 文档中配置的所有内容:https://edgeguides.rubyonrails.org/security.html

Content-Security-Policy 的 Rails 5.2 示例:

# config/initializers/content_security_policy.rb    
    Rails.application.config.content_security_policy do |policy|
      policy.frame_ancestors :self, 'some_website_that_embeds_your_app.com'
    end

控制器特定更改策略的示例:

# Override policy inline
class PostsController < ApplicationController
  content_security_policy do |p|
    p.frame_ancestors :self, 'some_other_website_that_can_embed_posts.com'
  end
end

【讨论】:

也可以将 lambda 用于动态值:p.frame_ancestors :self, -&gt; company&amp;.allowed_domain || 'none' 我正在使用frame_ancestors,它适用于所有浏览器,但 Safari 除外。有什么见解吗? @Matt - 我相信 Safari 目前会阻止 3rd 方 iframe 存储 cookie - 这是在 Safari 中使用 iframe 的主要限制,可能是您的问题的原因。据我所知,没有好的解决方法。检查此堆栈溢出以获取更多信息:***.com/questions/59723056/…【参考方案4】:

如果你想完全去除header,你可以创建一个after_action过滤器:

class FilesController < ApplicationController
  after_action :allow_iframe, only: :embed

  def embed
  end

private

  def allow_iframe
    response.headers.except! 'X-Frame-Options'
  end
end

或者,当然,您可以编码 after_action 以将值设置为不同的值:

class FacebookController < ApplicationController
  after_action :allow_facebook_iframe

private

  def allow_facebook_iframe
    response.headers['X-Frame-Options'] = 'ALLOW-FROM https://apps.facebook.com'
  end
end

请注意,您需要在调试时清除某些浏览器(我是 Chrome)中的缓存。

【讨论】:

你如何让它在redirect_to上工作? (我现在正在尝试使用我的 Angular 应用程序,但它不工作) 我假设包含redirect_to 的操作和它重定向到的操作都需要应用这个。您是否遇到特定错误?听起来像是 Stack Overflow 上的一个很好的新问题! 我意识到我有 after_action 之前它被重定向到重定向到 Angular 路由的最终控制器操作。谢谢! after_action 中执行此操作不是必需,尽管这样做很方便,例如在 Frontend::BaseController 中,它适用于整个前端。你也可以在一个动作中运行response.headers.except! ... 截至目前,无法在 Chrome 中使用。控制台错误是“加载'child'时遇到无效的'X-Frame-Options'标头:'ALLOW-FROM parent'不是可识别的指令。标头将被忽略。”标记为不会在 Chromium 中修复,还有一个替代方案:“'frame-ancestors' 已在 Chrome 和 Firefox 中发布,并且是支持此功能的正确方法。” bugs.chromium.org/p/chromium/issues/detail?id=129139

以上是关于如何在 Rails 4 中覆盖控制器或动作的 X-Frame-Options的主要内容,如果未能解决你的问题,请参考以下文章

每个动作的 Rails 布局?

如何重用 Rails 中嵌套控制器的渲染动作?

Rails-覆盖在使用部分或特定控制器视图时的页面元素

如何在 Rails 4 中使用关注点

如何直接从 Rails 控制器返回 HTML?

Rails 3:如何获取当前布局的名称?