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

88

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"

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

Крис Питерс
источник

Ответы:

137

Если вы хотите полностью удалить заголовок, вы можете создать 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, но оно не работает)
kittyminky
Я предполагаю, redirect_toчто это необходимо применить как к действию, содержащему, так и к действию, на которое он перенаправляет. Вы получаете конкретную ошибку? Похоже, хороший новый вопрос о переполнении стека!
Крис Питерс
Я понял, что у меня был after_action до того, как он был перенаправлен на последнее действие контроллера, которое перенаправляет на Angularмаршруты. Спасибо!
kittyminky
Это не обязательно делать в a after_action, хотя это удобно, например, в a, Frontend::BaseControllerгде это применяется ко всему интерфейсу. Вы также можете запустить response.headers.except! ...действие.
codener
2
На данный момент не работает в Chrome. Ошибка консоли: «При загрузке дочернего элемента обнаружен недопустимый заголовок« X-Frame-Options »:« ALLOW-FROM parent »не является распознанной директивой. Заголовок будет проигнорирован». Отмечено как не исправит в Chromium, с альтернативой: «frame-ancestors» поставляется как в Chrome, так и в Firefox, и это правильный способ поддержки этой функции ». bugs.chromium.org/p/chromium/issues/detail?id=129139
richardkmiller 09
5

Я просто хотел включить сюда обновленный ответ для всех, кто найдет эту ссылку, пытаясь выяснить, как разрешить встраивание вашего 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
armont_development
источник
Также можно использовать лямбду для динамических значений:p.frame_ancestors :self, -> { company&.allowed_domain || 'none' }
Шарагоз
0

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

camilo.forero
источник