Как переопределить X-Frame-Options для контроллера или действия в Rails 4

Rails 4, кажется, устанавливает значение по умолчанию SAMEORIGIN для X-Frame-Options HTTP-заголовка ответа. Это отлично для безопасности, но не позволяет частям вашего приложения быть доступными в iframe другом домене.

Вы можете изменить значение X-Frame-Options глобально, используя параметр config.action_dispatch.default_headers:

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

Но как отменить его для одного контроллера или действия?


person Chris Peters    schedule 26.08.2013    source источник


Ответы (4)


Если вы хотите полностью удалить заголовок, вы можете создать фильтр 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 для меня) во время отладки.

person Chris Peters    schedule 26.08.2013
comment
Как бы вы заставили это работать с redirect_to? (Сейчас я пытаюсь использовать свое приложение Angular, но оно не работает) - person kittyminky; 29.10.2014
comment
Я предполагаю, что это необходимо применить как к действию, содержащему redirect_to, так и к действию, на которое он перенаправляет. Вы получаете конкретную ошибку? Похоже, хороший новый вопрос о переполнении стека! - person Chris Peters; 30.10.2014
comment
Я понял, что у меня был after_action до, он был перенаправлен на последнее действие контроллера, которое перенаправляет на Angular маршруты. Спасибо! - person kittyminky; 30.10.2014
comment
Это не требуется делать это в after_action, хотя это удобно, например, в Frontend::BaseController, где он применяется ко всему интерфейсу. Вы также можете запустить response.headers.except! ... внутри действия. - person codener; 18.05.2016
comment
На данный момент не работает в Chrome. Ошибка консоли - недопустимый заголовок «X-Frame-Options», обнаруженный при загрузке «дочернего» элемента: «ALLOW-FROM parent» не является распознанной директивой. Заголовок будет проигнорирован. Отмечено как не исправит в Chromium, с альтернативой: «frame-ancestors» поставляется как в Chrome, так и в Firefox и является правильным способом поддержки этой функции. bugs.chromium.org/p/chromium/issues/detail?id= 129139 - person richardkmiller; 09.01.2018

Я просто хотел включить здесь обновленный ответ для всех, кто найдет эту ссылку, пытаясь выяснить, как разрешить встраивание вашего Rails-приложения в I-Frame и столкнуться с проблемами.

На момент написания этой статьи, 28 мая 2020 года, изменения X-Frame-Options, вероятно, не являются лучшим решением вашей проблемы. Опция «РАЗРЕШИТЬ-ОТ» полностью запрещена всеми основными браузерами.

Современное решение - реализовать Content-Security-Policy и установить политику frame_ancestors. Ключ frame_ancestors указывает, какие домены могут встраивать ваше приложение в качестве iframe. В настоящее время он поддерживается основными браузерами и отменяет ваши параметры X-Frame. Это позволит вам предотвратить кликджекинг (с которым X-Frame-Options должен был помочь до того, как он в значительной степени устарел) и заблокировать ваше приложение в современной среде.

Вы можете настроить Content-Security-Policy с Rails 5.2 в инициализаторе (пример ниже), а для Rails ‹5.2 вы можете использовать гем вроде Secure Headers: https://github.com/github/secure_headers

Вы также можете переопределить спецификации политики для контроллера / действия, если хотите.

Content-Security-Policies отлично подходят для расширенной защиты. Ознакомьтесь со всем, что вы можете настроить, в документации Rails: https://edgeguides.rubyonrails.org/security.html

Пример Rails 5.2 для Content-Security-Policy:

# 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
person armont_development    schedule 28.05.2020
comment
Также можно использовать лямбда для динамических значений: p.frame_ancestors :self, -> { company&.allowed_domain || 'none' } - person Sharagoz; 06.10.2020
comment
Я использую frame_ancestors, и он работает во всех браузерах, кроме Safari. Любое понимание? - person Matt; 02.12.2020
comment
@Matt - я считаю, что Safari в настоящее время не позволяет сторонним iframe сохранять файлы cookie - это серьезное ограничение использования iframe в Safari и может быть причиной вашей проблемы. Насколько я знаю, хороших обходных путей нет. Проверьте это переполнение стека для получения дополнительной информации: https://stackoverflow.com/questions/59723056/safari-13-iframe-blocks-cors-cookies - person armont_development; 02.12.2020

Приведенные выше ответы действительно помогли мне, но в 2021 году, используя приложение Rails 4.2, мне нужно было отключить X-Frame-Options и указать Content-Security-Policy только для пары URL-адресов.

В частности, я использую 2checkout в качестве поставщика платежей, и они открывают некоторые URL-адреса в окнах iframe ....

Вот как я это сделал

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
person Dagmar    schedule 04.06.2021

Для Rails 5+ используйте вместо этого response.set_header('X-Frame-Options', 'ALLOW-FROM https://apps.facebook.com'). Или, если ALLOW-FROM не работает и вам нужно быстрое исправление, вы можете установить для него ALLOWALL

person camilo.forero    schedule 04.08.2020
comment
Оба эти параметра (ALLOW-FROM и ALLOWALL) больше не действительны: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ - person ar31an; 30.04.2021