ActionController :: InvalidAuthenticityToken


148

Нижче наведена помилка, викликана формою в моєму додатку Rails:

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):

Це відбувається для кожного не getзапиту, і, як бачите, authenticity_tokenвін є.

Відповіді:


207

У мене був той самий випуск, але зі сторінками, які були кешовані. Сторінки отримують буферизований маркер автентичності та всі дії за допомогою методів "поставити / поставити / видалити", якщо їх визнано спробами підробки. Помилка (422 Unprocessable Entity) повернуто користувачеві.

Рішення для Rails 3:
Додати:

 skip_before_filter :verify_authenticity_token  

або як "sagivo", зазначене в Rails 4, додають:

 skip_before_action :verify_authenticity_token

На сторінках, які виконують кешування.

Як @toobulkeh прокоментував це не вразливість в :index, :showдіях, але остерігайтеся використовувати це на :put, :postдій.

Наприклад:

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

Довідка: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html

Примітка, додана barlop- Ралі 4.2, застарілий skip_before_filter на користь skip_beforecturing https://guides.rubyonrails.org/4_2_release_notes.html "Сімейство методів * _фільтру вилучено з документації. Їх використання перешкоджає на користь * _action сім'я методів "

Для Rails 6 (як "collimarco" вказував) ви можете використовувати skip_forgery_protectionта безпечно використовувати його для REST API, який не використовує дані сеансу.


3
Це, мабуть, не так, я не знав caches_page перед вашою публікацією. Але я перевірю caches_page , спасибі
Микита Рибак

7
в рейках 4skip_before_action :verify_authenticity_token
Сагів Офек

88
Це не вразливість?
квантовапотока

6
це не вразливість :index, :showдій. Але будьте обережніше ставити це на :put, :postдії!
toobulkeh

14
Хоча я згоден, у вас іноді трапляються випадки, коли це потрібно (як, можливо, один раз у житті), але вам потрібно усвідомити, що ви виправляєте безпеку, відключаючи безпеку. Не рекомендується
еквівалент8

77

Для мене причиною цього питання в Rails 4 було відсутність,

<%= csrf_meta_tags %>

Рядок у моєму головному макеті програми. Я випадково видалив його, коли я переписав свій макет.

Якщо це не в основному макеті, він знадобиться вам на будь-якій сторінці, на якій ви хочете маркер CSRF.


2
Ми також отримуємо цю помилку. Але це перервано. Чи може це бути причиною чи це не вплине на кожен запит із помилкою?
Райан-Ніл Мес

@ Ryan-NealMes, якщо у вашому шаблоні відсутній цей рядок, ви отримаєте помилку. Тож можливо, деякі шаблони мають, а інші - ні.
Джеймс Макмахон

1
@JamesMcMahon дякую, я зрозумів, що моя справа насправді викликана тим, що користувачі очищають свої файли cookie чи блокують файли cookie. Вивчили вантажі з цього питання!
Райан-Ніл Мес

61

Існує кілька причин цієї помилки (що стосується Rails 4).

1. Перевірте <%= csrf_meta_tags %>присутність у макеті сторінки

2. перевірте, що маркер автентичності надсилається з дзвінками AJAX, якщо використовується form_forпомічник з remote: trueопцією. Якщо ви не можете включити рядок <%= hidden_field_tag :authenticity_token, form_authenticity_token %>із блоком форми.

3. Якщо запит надсилається з кешованої сторінки, використовуйте кешування фрагментів, щоб виключити частину сторінки, яка надсилає запит, наприклад, button_toтощо, інакше маркер буде необов’язковим / недійсним.

Я б не хотів звести нанівець захист csrf ...


csrf_meta_tags має бути в <head>? Як я можу бути впевнений, що він не суперечить турболинкам?
виблискують

37

Просто додавши authenticity_tokenформу, виправили це для мене.

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

3
Rails, як передбачається, надсилає маркер за замовчуванням. Ми не хочемо це чітко вказувати. Я відчуваю, що жетон якось змінюється в цій ситуації тут.
Абхі

1
Однак якщо ви створили форму, не використовуючи помічників, слід ввести її вручну.
Андре Гімараес Саката

30

Маркер автентичності - це випадкове значення, створене у вашому представленні для підтвердження подання запиту із форми на вашому веб-сайті, а не деінде. Це захищає від атак CSRF:

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

Перевірте, хто такий клієнт / IP, схоже, що вони використовують ваш сайт, не завантажуючи ваші перегляди.

Якщо вам потрібно буде налагоджувати далі, це питання є гарним місцем для початку: Розуміння маркера автентичності Rails

Відредаговано для пояснення: Це означає, що вони закликають дію обробити вашу форму подання, не надаючи форму на вашому веб-сайті. Це може бути шкідливим (скажімо, розміщуючи коментарі зі спамом) або може означати, що клієнт намагається безпосередньо використовувати API вашого веб-сервісу. Ви єдиний, хто може відповісти на це за характером вашого продукту та аналізуючи ваші запити.


1
Дякую, але я вже знаю, що таке марка автентичності. Перевірте, хто такий клієнт / IP, схоже, що вони використовують ваш сайт, не завантажуючи ваші перегляди. Вибачте, що означає "без завантаження переглядів"?
Микита Рибак

1
Я маю на увазі, що хтось (можливо, спамер) може надсилати дані у вашу форму, не проходячи через користувальницький інтерфейс програми. Це можна зробити, наприклад, за допомогою програми командного рядка, наприклад curl.
Джон Топлі

Джон має це правильно. Це означає, що вони закликають дію обробити вашу форму подання, не надаючи форму на свій веб-сайт. Це може бути шкідливим (скажімо, розміщуючи коментарі зі спамом) або може означати, що клієнт намагається безпосередньо використовувати API вашого веб-сервісу. Ви єдиний, хто може відповісти на це за характером вашого продукту та аналізуючи ваші запити.
Winfield

Гаразд, я неправильно зрозумів коментар Вінфілда. Я думав, що додаток не якимось чином налаштовано на "завантаження моїх поглядів" під час використання браузера.
Микита Рибак

1
У мене також була інша думка, ці запити включають маркер, але це неправдиво. Це може бути спричинене кешуванням сторінки, що надає вашу форму, або чимось іншим, що потенційно спричиняє несвіжу версію форми.
Winfield

26

ActionController::InvalidAuthenticityTokenтакож може бути викликана неправильно налаштованим зворотним проксі. Це так, якщо в сліді стека ви отримуєте такий рядок Request origin does not match request base_url.

Використовуючи зворотний проксі (наприклад, nginx) в якості приймача для HTTPS-запиту та передаючи запит незашифрованим до бекенду (наприклад, програма Rails), бекенд (точніше: Rack) очікує, що деякі заголовки мають більше інформації про вихідний запит клієнта. щоб мати можливість застосовувати різні завдання з обробки та заходи безпеки.

Детальніше можна ознайомитись тут: https://github.com/rails/rails/isissue/22965 .

TL; DR: рішення - додати кілька заголовків:

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;
}

Нічого собі, я три години шукав рішення для цього, і це було, дякую!
evexoio

велике дякую за 6 годин спроб вирішити це на стороні рейок
Джо Половина обличчя

18

занадто пізно, щоб відповісти, але я знайшов рішення.

Коли ви визначаєте, що у вас є форма html, то ви пропускаєте рядок маркера аутентифікації, який слід надіслати контролеру з міркувань безпеки. Але використовуючи помічник форми рейки для створення форми, ви отримуєте щось на зразок наступного

<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>

Таким чином, рішення проблеми полягає в тому, щоб додати поле автентичності_токена або використовувати допоміжні форми рейки, а не видаляти, зменшувати чи модернізувати рейки.


9

Якщо ви зробили rake rails:updateабо нещодавно змінили свій файл config/initializers/session_store.rb, це може бути симптомом старих файлів cookie у веб-переглядачі. Сподіваємось, це зроблено в програмі dev / test (це було для мене), і ви можете просто очистити всі файли cookie браузера, пов’язані з відповідним доменом.

Якщо це є у виробництві, і ви змінилися key, подумайте про те, щоб повернути його назад, щоб використовувати старі файли cookie (<- лише міркування).


Так! Для мене виникнення порожнього session_store.rb викликало помилку.
лафебер

6

У мене виникла ця проблема з викликами javascript. Я вирішив це, просто вимагаючи jquery_ujs у файл application.js.


Так правильно, у мене також була ця проблема, і я додав jquery_ujs у js програми. Це спрацювало.
Абхі

3

У нас була така ж проблема, але помітили, що це стосується лише запитів, що використовують http: //, а не з https: //. Причина була secure: trueв session_store:

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

Виправлено за допомогою HTTPS ~ всюди :)


Я зіткнувся з цим під час використання rails s(не-SSL) замість кінцевої точки SSL, яку я встановив для розробки. Тільки до того, як я прочитав ваш коментар, я зрозумів, що роблю. Як тільки я перейшов до використання SSL, все почало працювати знову. Дякую!
Карл Вільбур

1
Я зіткнувся з цим питанням у розвитку. Замість того, щоб secure: trueя писавsecure: !Rails.env.development?
убий

1

Для рейок 5 краще додати, protect_from_forgery prepend: trueніж пропуститиverify_authentication_token


5
Чому? Чи можете ви додати посилання?
kwerle


0

У мене була ця проблема, і причина в тому, що я скопіював і вставив контролер у свою програму. Мені потрібно було перейти ApplicationControllerнаApplicationController::Base


0

У мене був той самий випуск у localhost. Я змінив домен для програми, але в URL-адресах та файлах хостів ще був старий домен. Оновив файл закладок і хостів, щоб використовувати новий домен, і тепер усе працює добре.


0

Можливо, у вас налаштування NGINX для HTTPS, але ваші сертифікати недійсні? У мене була аналогічна проблема в минулому, і перенаправлення з http на https вирішило проблему


0

Я перевірив наявність <% = csrf_meta_tags%> і очищення файлів cookie в браузері працював на мене.


0

Дотримуючись рекомендацій Маяка Chrome для швидшого завантаження програми, я асинхронізував свій Javascript:

views/layout/application.html.erb

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

Це зламало все і отримало ту помилку Token для моїх віддалених форм. Видалення async: trueвиправлено проблему.


0

Ця відповідь набагато більш конкретна для Ruby on Rails, але, сподіваємось, комусь це допоможе.

Вам потрібно включити маркер CSRF до кожного не-GET запиту. Якщо ви звикли користуватися JQuery, у Rails є бібліотека помічників, яка називається, jquery-ujsяка створюється на ній і додає певну приховану функціональність. Одне з речей, яке він робить, автоматично включає маркер CSRF у кожен ajaxзапит. Дивіться тут .

Якщо ви відключитесь від нього, як я, ви можете виявити помилку. Ви можете просто надіслати маркер вручну або скористатися іншою бібліотекою, щоб допомогти скребти маркер з DOM. Дивіться цю публікацію для більш детальної інформації.


-1

У рейках 5 нам потрібно додати 2 рядки коду

    skip_before_action :verify_authenticity_token
    protect_from_forgery prepend: true, with: :exception

-2

Встановлення

gem 'remotipart' 

може допомогти


3
Хоча це може бути відповіддю, але також корисно включити істотну частину відповіді та пояснити, чому / як це працює.
Рой Лі

-15

Проблема вирішена шляхом пониження до 2.3.5 з 2.3.8. (а також сумнозвісна проблема "Вас перенаправляють".)


@Flip, можливо, це ідея оновити прийняту відповідь?
lafeber
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.