Token Autentyczności Rails 4
Pracowałem nad nową aplikacją Rails 4 (na Ruby 2.0.0-p0), kiedy napotkałem problemy z tokenem autentyczności.
Podczas pisania kontrolera odpowiadającego na json (używając metody klasy respond_to
), dotarłem do akcji create
, którą zacząłem otrzymywać ActionController::InvalidAuthenticityToken
, kiedy próbowałem utworzyć rekord używając curl
.
Upewniłem się, że ustawiłem -H "Content-Type: application/json"
i ustawiłem dane za pomocą -d "<my data here>"
, ale i tak bez powodzenia.
Próbowałem napisać ten sam kontroler używając Rails 3.2 (Na Ruby 1.9.3) i nie mam problemy z autentycznością. Szukałem i zobaczyłem, że w Rails 4 zaszły pewne zmiany z tokenami autentyczności. Z tego co rozumiem, nie są już automatycznie wstawiane do formularzy? Przypuszczam, że w jakiś sposób wpływa to na typy treści innych niż HTML.
Czy jest jakiś sposób, aby obejść to bez konieczności żądania formularza HTML, przechwytywania tokenu autentyczności, a następnie składania kolejnego żądania z tym tokenem? A może zupełnie brakuje mi czegoś, co jest całkowicie oczywiste?
Edit: właśnie próbowałem stworzyć nowy rekord w nowej aplikacji Rails 4 używając rusztowania bez zmiany czegokolwiek i mam ten sam problem, więc myślę, że to nie jest coś, co zrobiłem.
5 answers
Chyba właśnie to rozgryzłem. Zmieniłem (nowy) domyślny
protect_from_forgery with: :exception
Do
protect_from_forgery with: :null_session
Zgodnie z komentarzem w ApplicationController
.
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
Możesz zobaczyć różnicę patrząc na źródło request_forgery_protecton.rb
, a dokładniej na następujące linie:
In Rails 3.2:
# This is the method that defines the application behavior when a request is found to be unverified.
# By default, \Rails resets the session when it finds an unverified request.
def handle_unverified_request
reset_session
end
In Rails 4:
def handle_unverified_request
forgery_protection_strategy.new(self).handle_unverified_request
end
Który wywoła następujący :
def handle_unverified_request
raise ActionController::InvalidAuthenticityToken
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-05 16:26:45
Zamiast wyłączać ochronę csrf, lepiej dodać następujący wiersz kodu do formularza
<%= tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) %>
I jeśli używasz form_for lub form_tag do generowania formularza, to automatycznie doda powyższy wiersz kodu w formularzu
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-23 04:00:03
Dodanie następującej linijki do formularza zadziałało dla mnie:
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-24 23:56:44
Nie wydaje mi się, aby było dobrze wyłączać ochronę CSRF tak długo, jak długo nie implementujesz wyłącznie API.
Przeglądając dokumentację API Rails 4 dla ActionController odkryłem, że można wyłączyć ochronę przed fałszerstwami dla każdego kontrolera lub bazy metod.
Na przykład, aby wyłączyć ochronę CSRF dla metod, których można użyć
class FooController < ApplicationController
protect_from_forgery except: :index
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-27 01:47:23