ActionController :: InvalidAuthenticityToken

148

Di bawah ini adalah kesalahan, yang disebabkan oleh formulir di aplikasi Rails saya:

Processing UsersController#update (for **ip** at 2010-07-29 10:52:27) [PUT]
  Parameters: {"commit"=>"Update", "action"=>"update", "_method"=>"put", "authenticity_token"=>"ysiDvO5s7qhJQrnlSR2+f8jF1gxdB7T9I2ydxpRlSSk=", **more parameters**}

ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

Ini terjadi untuk setiap non- getpermintaan dan, seperti yang Anda lihat, authenticity_tokenada di sana.

Nikita Rybak
sumber

Jawaban:

207

Saya memiliki masalah yang sama tetapi dengan halaman yang di-cache halaman. Halaman mendapat buffered dengan token keaslian basi dan semua tindakan menggunakan metode post / put / delete yang diakui sebagai upaya pemalsuan. Kesalahan (422 Entitas yang tidak dapat diproses) dikembalikan ke pengguna.

Solusi untuk Rails 3:
Tambahkan:

 skip_before_filter :verify_authenticity_token  

atau seperti yang "sagivo" tunjukkan di Rails 4 tambahkan:

 skip_before_action :verify_authenticity_token

Pada halaman yang melakukan caching.

Sebagai @toobulkeh berkomentar ini bukan kerentanan pada :index, :showtindakan, tapi berhati-hatilah menggunakan ini pada :put, :posttindakan.

Sebagai contoh:

 caches_page :index, :show  
 skip_before_filter :verify_authenticity_token, :only => [:index, :show]

Referensi: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html

Catatan ditambahkan oleh barlop- Rails 4.2 usang skip_before_filter yang mendukung skip_before_action https://guides.rubyonrails.org/4_2_release_notes.html "Metode keluarga * _filter telah dihapus dari dokumentasi. Penggunaannya tidak disarankan untuk mendukung * _action. keluarga metode "

Untuk Rails 6 (seperti yang ditunjukkan "collimarco") Anda dapat menggunakan skip_forgery_protectiondan aman untuk menggunakannya untuk REST API yang tidak menggunakan data sesi.

Szymon Jeż
sumber
3
Itu tidak mungkin terjadi, saya tidak tahu tentang caches_page sebelum posting Anda. Tapi saya akan memeriksa caches_page , terima kasih.
Nikita Rybak
7
di rel 4skip_before_action :verify_authenticity_token
Sagiv Ofek
88
Bukankah ini kerentanan?
quantumpotato
6
ini bukan kerentanan pada :index, :showtindakan. Tapi hati-hati dalam melakukan ini :put, :post!
toobulkeh
14
walaupun saya setuju Anda kadang-kadang memiliki kasus di mana ini diperlukan (seperti mungkin sekali seumur hidup) tetapi Anda perlu menyadari bahwa Anda memperbaiki keamanan dengan menonaktifkan keamanan. Tidak direkomendasikan
setara dengan
77

Bagi saya penyebab masalah ini di bawah Rails 4 adalah hilang,

<%= csrf_meta_tags %>

Baris dalam tata letak aplikasi utama saya. Saya tidak sengaja menghapusnya ketika saya menulis ulang tata letak saya.

Jika ini tidak ada di tata letak utama Anda akan membutuhkannya di halaman yang Anda inginkan token CSRF.

James McMahon
sumber
2
Kami juga menerima kesalahan ini. Tapi itu saling terkait. Mungkinkah ini alasannya atau tidakkah hal ini memengaruhi setiap permintaan dengan kesalahan?
Ryan-Neal Mes
@ Ryan-NealMes, jika template Anda tidak ada pada baris itu, Anda akan mendapatkan kesalahan. Jadi, mungkin beberapa templat Anda memilikinya dan yang lain tidak.
James McMahon
1
@JamesMcMahon terima kasih, saya tahu kasus saya sebenarnya disebabkan oleh pengguna yang menghapus cookie mereka atau cookie diblokir. Belajar banyak dari pertanyaan ini!
Ryan-Neal Mes
61

Ada beberapa penyebab kesalahan ini, (terkait dengan Rails 4).

1. Periksa <%= csrf_meta_tags %>hadir dalam tata letak halaman

2. periksa token keaslian sedang dikirim dengan panggilan AJAX jika menggunakan form_forpenolong dengan remote: trueopsi. Jika tidak, Anda dapat menyertakan baris <%= hidden_field_tag :authenticity_token, form_authenticity_token %>dalam blok formulir.

3. Jika permintaan dikirim dari halaman yang di-cache, gunakan caching fragmen untuk mengecualikan bagian dari halaman yang mengirimkan permintaan misalnya button_todll. Jika token akan basi / tidak valid.

Saya akan enggan untuk membatalkan perlindungan csrf ...

GoodViber
sumber
csrf_meta_tags harus di dalam <head>? Bagaimana saya bisa yakin itu tidak bertentangan dengan turbolinks?
kilau
37

Hanya menambahkan authenticity_tokenformulir dalam memperbaikinya untuk saya.

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
Deepak Mahakale
sumber
3
Rel seharusnya mengirim token secara default. Kami tidak ingin menentukannya secara eksplisit. Saya merasa token berubah entah bagaimana dalam situasi ini di sini.
Abhi
1
Namun, jika Anda membuat formulir tanpa menggunakan pembantu, Anda harus meletakkannya secara manual.
André Guimarães Sakata
30

Token keaslian adalah nilai acak yang dihasilkan dalam tampilan Anda untuk membuktikan bahwa permintaan diajukan dari formulir di situs Anda, bukan di tempat lain. Ini melindungi terhadap serangan CSRF:

http://en.wikipedia.org/wiki/Cross-site_request_forgery

Periksa untuk melihat siapa klien / IP itu, sepertinya mereka menggunakan situs Anda tanpa memuat tampilan Anda.

Jika Anda perlu melakukan debug lebih lanjut, pertanyaan ini adalah tempat yang baik untuk memulai: Memahami Token Keaslian Rails

Diedit untuk menjelaskan: Ini berarti mereka memanggil tindakan untuk memproses pengiriman formulir Anda tanpa pernah menyerahkan formulir Anda di situs web Anda. Ini bisa berbahaya (katakanlah mengeposkan komentar spam) atau itu bisa menunjukkan pelanggan mencoba menggunakan API layanan web Anda secara langsung. Hanya Anda yang dapat menjawabnya berdasarkan sifat produk Anda dan menganalisis permintaan Anda.

Winfield
sumber
1
Terima kasih, tapi saya sudah tahu apa itu token keaslian. Periksa untuk melihat siapa klien / IP itu, sepertinya mereka menggunakan situs Anda tanpa memuat tampilan Anda. Maaf, apa artinya "tanpa memuat tampilan"?
Nikita Rybak
1
Maksud saya, seseorang (mungkin seorang spammer) dapat mengirimkan data ke formulir Anda tanpa melalui antarmuka pengguna aplikasi Anda. Mungkin untuk melakukan ini menggunakan program baris perintah seperti curl, misalnya.
John Topley
John benar sekali. Ini berarti mereka memanggil tindakan untuk memproses pengiriman formulir Anda tanpa pernah menyerahkan formulir Anda di situs web Anda. Ini bisa berbahaya (katakanlah mengeposkan komentar spam) atau itu bisa menunjukkan pelanggan mencoba menggunakan API layanan web Anda secara langsung. Hanya Anda yang dapat menjawabnya berdasarkan sifat produk Anda dan menganalisis permintaan Anda.
Winfield
Ok, saya salah mengerti komentar Winfield. Saya pikir aplikasi itu entah bagaimana tidak dikonfigurasi untuk 'memuat pandangan saya' ketika saya menggunakan browser.
Nikita Rybak
1
Saya juga punya pemikiran lain, permintaan ini termasuk token, tapi itu tidak valid. Ini bisa disebabkan oleh caching halaman yang merender formulir Anda atau sesuatu yang menyebabkan versi basi formulir berpotensi.
Winfield
27

ActionController::InvalidAuthenticityTokenjuga dapat disebabkan oleh proksi terbalik yang salah konfigurasi. Ini adalah kasus jika dalam jejak stack, Anda mendapatkan garis yang terlihat seperti Request origin does not match request base_url.

Saat menggunakan proksi terbalik (seperti nginx) sebagai penerima untuk permintaan HTTPS dan mengirimkan permintaan yang tidak dienkripsi ke backend (seperti aplikasi Rails), backend (lebih khusus: Rack) mengharapkan beberapa header dengan informasi lebih lanjut tentang permintaan klien asli agar dapat menerapkan berbagai tugas pemrosesan dan langkah-langkah keamanan.

Rincian lebih lanjut tersedia di sini: https://github.com/rails/rails/issues/22965 .

TL; DR: solusinya adalah menambahkan beberapa header:

upstream myapp {
  server              unix:///path/to/puma.sock;
}

location / {
  proxy_pass        http://myapp;
  proxy_set_header  Host $host;
  proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header  X-Forwarded-Proto $scheme;
  proxy_set_header  X-Forwarded-Ssl on; # Optional
  proxy_set_header  X-Forwarded-Port $server_port;
  proxy_set_header  X-Forwarded-Host $host;
}
vmarquet
sumber
Wow, saya sudah mencari 3 jam untuk solusi untuk ini, dan ini dia, terima kasih!
evexoio
terima kasih banyak 6 jam untuk mencoba menyelesaikan ini di sisi rel
Joe Half Face
18

sudah terlambat untuk menjawab tetapi saya menemukan solusinya.

Ketika Anda menentukan Anda memiliki bentuk html maka Anda kehilangan string token otentikasi yang harus dikirim ke controller untuk alasan keamanan. Tetapi ketika Anda menggunakan rel bentuk helper untuk menghasilkan formulir Anda mendapatkan sesuatu seperti mengikuti

<form accept-charset="UTF-8" action="/login/signin" method="post">
  <div style="display:none">
    <input name="utf8" type="hidden" value="&#x2713;">
    <input name="authenticity_token" type="hidden" 
      value="x37DrAAwyIIb7s+w2+AdoCR8cAJIpQhIetKRrPgG5VA=">
    .
    .
    .
  </div>
</form>

Jadi solusi untuk masalah ini adalah dengan menambahkan bidang authenticity_token atau menggunakan rel bentuk helpers daripada menghapus, menurunkan, atau memutakhirkan rel.

amjad
sumber
9

Jika Anda telah rake rails:updateatau baru-baru ini mengubah Anda config/initializers/session_store.rb, ini mungkin merupakan gejala cookie lama di browser. Semoga ini dilakukan di dev / test (untuk saya), dan Anda bisa menghapus semua cookie browser yang terkait dengan domain yang dimaksud.

Jika ini sedang dalam produksi, dan Anda berubah key, pertimbangkan untuk mengubahnya kembali untuk menggunakan cookie lama (<- hanya spekulasi).

Kross
sumber
Iya! Bagi saya, memiliki session_store.rb kosong menyebabkan kesalahan.
lafeber
6

Saya punya masalah dengan panggilan javascript. Saya memperbaikinya dengan hanya memerlukan jquery_ujs ke file application.js.

Michael Koper
sumber
Ya benar, saya juga mengalami masalah ini dan saya menambahkan jquery_ujs di js aplikasi. Itu berhasil.
Abhi
3

Kami memiliki masalah yang sama, tetapi memperhatikan bahwa itu hanya untuk permintaan yang menggunakan http: // dan tidak dengan https: //. Penyebabnya adalah secure: trueuntuk session_store:

Rails.application.config.session_store(
  :cookie_store,
  key: '_foo_session',
  domain: '.example.com',
  secure: true
)

Diperbaiki dengan menggunakan HTTPS ~ di mana saja :)

Darep
sumber
Saya menemukan ini ketika menggunakan rails s(non-SSL) alih-alih titik akhir SSL yang telah saya atur untuk pengembangan. Baru setelah saya membaca komentar Anda, saya menyadari apa yang saya lakukan. Setelah saya kembali menggunakan SSL, semuanya mulai berfungsi lagi. Terima kasih!
Karl Wilbur
1
Saya menghadapi masalah ini dalam pengembangan. Alih-alih secure: truesaya menulissecure: !Rails.env.development?
murb
1

Untuk rel 5, lebih baik menambahkan protect_from_forgery prepend: truedaripada melewatkanverify_authentication_token

aadeshere1
sumber
5
Mengapa? Bisakah Anda menambahkan referensi?
kwerle
1

Menambahkan

//= require rails-ujs 

di

\app\assets\javascripts\application.js
Maicon Douglas
sumber
0

Saya punya masalah ini dan alasannya adalah karena saya menyalin dan menempelkan pengontrol ke aplikasi saya. Saya perlu untuk mengubah ApplicationControllerkeApplicationController::Base

pengguna2954587
sumber
0

Saya memiliki masalah yang sama di localhost. Saya telah mengubah domain untuk aplikasi, tetapi dalam URL dan file host masih ada domain lama. Diperbarui bookmark browser dan file host saya untuk menggunakan domain baru dan sekarang semuanya berfungsi dengan baik.

MoD
sumber
0

Mungkin Anda memiliki pengaturan NGINX untuk HTTPS tetapi sertifikat Anda tidak valid? Saya pernah mengalami masalah yang sama di masa lalu dan mengalihkan dari http ke https memecahkan masalah

montrealmike
sumber
0

Saya telah memeriksa <% = csrf_meta_tags%> ada dan menghapus cookie di browser berfungsi untuk saya.

Praveen KJ
sumber
0

Mengikuti rekomendasi Chrome Lighthouse untuk memuat aplikasi yang lebih cepat, saya telah menyinkronkan Javascript saya:

views/layout/application.html.erb

<%= javascript_include_tag 'application', 'data-turbolinks-track' => 'reload', async: true %>

Ini mematahkan segalanya dan mendapatkan kesalahan Token untuk formulir jarak jauh saya. Menghapus async: truememperbaiki masalah.

Maxence
sumber
0

Jawaban ini jauh lebih spesifik untuk Ruby on Rails, tetapi mudah-mudahan ini akan membantu seseorang.

Anda harus memasukkan token CSRF dengan setiap permintaan non-GET. Jika Anda terbiasa menggunakan JQuery, Rails memiliki pustaka penolong yang disebut jquery-ujsbuild di atasnya dan menambahkan beberapa fungsi tersembunyi. Salah satu hal yang dilakukannya adalah secara otomatis memasukkan token CSRF dalam setiap ajaxpermintaan. Lihat di sini .

Jika Anda beralih dari itu seperti yang saya lakukan, Anda mungkin menemukan diri Anda dengan kesalahan. Anda bisa mengirimkan token secara manual atau menggunakan perpustakaan lain untuk membantu mengikis token dari DOM. Lihat posting ini untuk detail lebih lanjut.

pengguna2490003
sumber
0

Untuk lingkungan pengembangan, saya mencoba banyak dari upaya ini untuk memperbaiki masalah ini, di Rails 6. Tidak ada yang membantu. Jadi, jika tidak ada saran yang sesuai untuk Anda, coba di bawah ini.

Satu-satunya solusi yang saya temukan adalah menambahkan file txt ke folder / tmp Anda.

Di direktori root aplikasi Anda, jalankan:

touch tmp/caching-dev.txt

Atau secara manual buat file dengan nama itu di folder / tmp Anda. Karena ini memperbaikinya untuk saya, saya menganggap akar masalah adalah konflik caching.

Twistedben
sumber
-1

Di rails 5, kita perlu menambahkan 2 baris kode

    skip_before_action :verify_authenticity_token
    protect_from_forgery prepend: true, with: :exception
giapnh
sumber
-2

Menginstal

gem 'remotipart' 

bisa membantu

Alexei.B
sumber
3
Meskipun ini mungkin jawabannya, tetapi juga membantu untuk memasukkan bagian penting dari jawaban dan menjelaskan mengapa / bagaimana cara kerjanya.
Roy Lee
-15

Masalah dipecahkan dengan menurunkan ke 2.3.5 dari 2.3.8. (Serta masalah terkenal 'Anda sedang diarahkan.')

Nikita Rybak
sumber
@Flip, mungkin ini ide untuk memperbarui jawaban yang diterima?
lafeber