Cara menimpa X-Frame-Options untuk pengontrol atau tindakan di Rails 4

89

Rails 4 tampaknya menyetel nilai default SAMEORIGINuntuk X-Frame-Optionsheader respons HTTP. Ini bagus untuk keamanan, tetapi tidak memungkinkan sebagian dari aplikasi Anda tersedia di iframedomain yang berbeda.

Anda dapat mengganti nilai X-Frame-Optionssecara global menggunakan config.action_dispatch.default_headerspengaturan:

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

Tetapi bagaimana Anda menimpanya hanya untuk satu pengontrol atau tindakan?

Chris Peters
sumber

Jawaban:

137

Jika Anda ingin menghapus header sepenuhnya, Anda dapat membuat after_actionfilter:

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

  def embed
  end

private

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

Atau, tentu saja, Anda dapat membuat kode after_actionuntuk menyetel nilainya menjadi sesuatu yang berbeda:

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

Perhatikan bahwa Anda perlu menghapus cache di browser tertentu (Chrome untuk saya) saat melakukan debug.

Chris Peters
sumber
Bagaimana Anda membuatnya bekerja di redirect_to? (Sedang mencoba sekarang dengan aplikasi Angular saya dan tidak berfungsi)
kittyminky
Saya akan berasumsi bahwa baik tindakan yang berisi redirect_todan tindakan yang dialihkan akan membutuhkan ini untuk diterapkan. Apakah Anda mendapatkan kesalahan tertentu? Sepertinya pertanyaan baru yang bagus tentang Stack Overflow!
Chris Peters
Saya menyadari saya memiliki after_action sebelum itu dialihkan ke tindakan pengontrol terakhir yang mengarahkan ke Angularrute. Terima kasih!
kittyminky
Hal ini tidak diperlukan untuk melakukan ini di after_action, meskipun akan berguna untuk melakukannya, misalnya di Frontend::BaseControllermana ini berlaku untuk seluruh frontend. Anda mungkin juga menjalankan response.headers.except! ...dalam suatu tindakan.
pembuat kode
2
Untuk saat ini, tidak berfungsi di Chrome. Kesalahan konsol adalah "Tajuk 'X-Frame-Options' tidak valid ditemukan saat memuat 'anak': 'ALLOW-FROM parent' bukan perintah yang dikenali. Tajuk akan diabaikan." Ditandai sebagai tidak dapat diperbaiki di Chromium, dengan alternatif: "'frame-leluhur' dikirimkan di Chrome dan Firefox, dan merupakan cara yang tepat untuk mendukung fungsi ini." bugs.chromium.org/p/chromium/issues/detail?id=129139
richardkmiller
8

Saya hanya ingin menyertakan jawaban yang diperbarui di sini untuk siapa saja yang menemukan tautan ini ketika mencoba mencari cara untuk memungkinkan aplikasi Rails Anda disematkan dalam I-Frame dan mengalami masalah.

Saat menulis ini, 28 Mei 2020, perubahan X-Frame-Options mungkin bukan solusi terbaik Anda untuk masalah Anda. Opsi "IZINKAN DARI" sama sekali tidak diizinkan oleh semua browser utama.

Solusi modern adalah dengan mengimplementasikan Content-Security-Policy dan menyetel kebijakan 'frame_ancestors'. Kunci 'frame_ancestors' menunjukkan domain apa yang dapat menyematkan aplikasi Anda sebagai iframe. Saat ini didukung oleh browser utama dan menggantikan X-Frame-Options Anda. Ini akan memungkinkan Anda untuk mencegah Clickjacking (yang awalnya dimaksudkan untuk membantu X-Frame-Options sebelum sebagian besar menjadi usang) dan mengunci aplikasi Anda di lingkungan modern.

Anda dapat mengatur Kebijakan-Keamanan-Konten dengan Rails 5.2 di penginisialisasi (contoh di bawah), dan untuk Rails <5.2 Anda dapat menggunakan permata seperti permata Secure Headers: https://github.com/github/secure_headers

Anda juga dapat mengganti spesifikasi kebijakan berdasarkan pengontrol / tindakan jika Anda mau.

Content-Security-Policies sangat bagus untuk perlindungan keamanan tingkat lanjut. Lihat semua hal yang dapat Anda konfigurasikan di dokumen Rails: https://edgeguides.rubyonrails.org/security.html

Contoh Rails 5.2 untuk 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

Contoh perubahan khusus pengontrol untuk kebijakan:

# 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
sumber
Dapat juga menggunakan lambda untuk nilai dinamis:p.frame_ancestors :self, -> { company&.allowed_domain || 'none' }
Sharagoz
Saya menggunakan frame_ancestorsdan berfungsi di setiap browser, kecuali Safari. Ada wawasan?
Matt
@Matt - Saya yakin Safari saat ini mencegah iframe pihak ketiga untuk menyimpan cookie - ini adalah batasan utama penggunaan iframe di Safari dan mungkin menjadi penyebab masalah Anda. Sejauh yang saya tahu tidak ada solusi yang baik. Periksa overflow tumpukan ini untuk informasi lebih lanjut: stackoverflow.com/questions/59723056/…
armont_development
0

Untuk Rails 5+, gunakan response.set_header('X-Frame-Options', 'ALLOW-FROM https://apps.facebook.com')saja. Atau jika ALLOW-FROMtidak berhasil dan Anda perlu perbaikan cepat, Anda dapat menyetelnya keALLOWALL

camilo.forero
sumber