Comment remplacer les options X-Frame pour un contrôleur ou une action dans Rails 4

88

Rails 4 semble définir une valeur par défaut SAMEORIGINpour l' X-Frame-Optionsen-tête de réponse HTTP. C'est excellent pour la sécurité, mais cela ne permet pas à certaines parties de votre application d'être disponibles dans un iframedomaine différent.

Vous pouvez remplacer la valeur de X-Frame-Optionsglobalement à l'aide du config.action_dispatch.default_headersparamètre:

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

Mais comment le remplacer pour un seul contrôleur ou une seule action?

Chris Peters
la source

Réponses:

137

Si vous souhaitez supprimer complètement l'en-tête, vous pouvez créer un after_actionfiltre:

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

  def embed
  end

private

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

Ou, bien sûr, vous pouvez coder le after_actionpour définir la valeur sur quelque chose de différent:

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

Notez que vous devez vider votre cache dans certains navigateurs (Chrome pour moi) lors du débogage.

Chris Peters
la source
Comment pourriez-vous faire fonctionner cela sur un redirect_to? (J'essaie en ce moment avec mon application Angular et cela ne fonctionne pas)
kittyminky
Je suppose que l'action contenant le redirect_toet l'action vers laquelle il redirige auraient besoin que cela soit appliqué. Obtenez-vous une erreur particulière? Sonne comme une bonne nouvelle question sur Stack Overflow!
Chris Peters
J'ai réalisé que j'avais le after_action avant qu'il ne soit redirigé vers l'action finale du contrôleur qui redirige vers les Angularroutes. Merci!
kittyminky
Il n'est pas nécessaire de le faire dans un after_action, bien qu'il soit pratique de le faire par exemple dans un Frontend::BaseControlleroù cela s'applique à l'ensemble du frontend. Vous pouvez aussi bien courir response.headers.except! ...dans une action.
codener
2
Pour l'instant, ne fonctionne pas dans Chrome. L'erreur de console est "En-tête" X-Frame-Options "non valide rencontré lors du chargement de" child ":" ALLOW-FROM parent "n'est pas une directive reconnue. L'en-tête sera ignoré." Marqué comme ne corrigera pas dans Chromium, avec une alternative: "'frame-ancestors' est disponible à la fois dans Chrome et Firefox, et c'est le bon moyen de prendre en charge cette fonctionnalité." bugs.chromium.org/p/chromium/issues/detail?id=129139
richardkmiller
5

Je voulais juste inclure une réponse mise à jour ici pour quiconque trouve ce lien en essayant de comprendre comment autoriser votre application Rails à être intégrée dans un I-Frame et à rencontrer des problèmes.

Au moment d'écrire ces lignes, le 28 mai 2020, les modifications des options X-Frame ne sont probablement pas votre meilleure solution à votre problème. L'option "ALLOW-FROM" a été totalement interdite par tous les principaux navigateurs.

La solution moderne consiste à mettre en œuvre une politique de sécurité du contenu et à définir une politique «frame_ancestors». La clé 'frame_ancestors' désigne les domaines qui peuvent intégrer votre application en tant qu'iframe. Il est actuellement pris en charge par les principaux navigateurs et remplace vos options X-Frame. Cela vous permettra d'empêcher le détournement de clic (que les options X-Frame étaient initialement destinées à aider avant qu'il ne devienne largement obsolète) et de verrouiller votre application dans un environnement moderne.

Vous pouvez configurer une politique de sécurité du contenu avec Rails 5.2 dans un initialiseur (exemple ci-dessous), et pour Rails <5.2, vous pouvez utiliser une gemme comme la gemme Secure Headers: https://github.com/github/secure_headers

Vous pouvez également remplacer les spécifications de politique sur une base contrôleur / action si vous le souhaitez.

Les politiques de sécurité du contenu sont parfaites pour les protections de sécurité avancées. Découvrez tout ce que vous pouvez configurer dans la documentation Rails: https://edgeguides.rubyonrails.org/security.html

Un exemple de Rails 5.2 pour une politique de sécurité de contenu:

# 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

Un exemple de modification spécifique d'un contrôleur dans une stratégie:

# 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
la source
Peut également utiliser un lambda pour les valeurs dynamiques:p.frame_ancestors :self, -> { company&.allowed_domain || 'none' }
Sharagoz
0

Pour Rails 5+, utilisez à la response.set_header('X-Frame-Options', 'ALLOW-FROM https://apps.facebook.com')place. Ou si ALLOW-FROMcela ne fonctionne pas et que vous avez besoin d'une solution rapide, vous pouvez le définir surALLOWALL

camilo.forero
la source