Naprawdę mam z tym problem, aw tym przypadku nie chcę pominąć filtru verify_authenticity_token
, ani zmienić na protect_from_forgery with: :null_session
.Nie można zweryfikować autentyczności tokenu CSRF Rails 4 Ajax nawet po ustawieniu nagłówka
W moim metody żądania, ja ustawienie nagłówka z tokenu CSRF następująco:
var token = document.querySelector("meta[name='csrf-token']").content;
xhr.setRequestHeader("X-CSRF-Token", token);
oraz poprzez dodanie punktu przerwania w moim kontrolera tak:
def verify_authenticity_token
binding.pry
super
end
I sprawdzeniu, że nagłówek jest ustawiony:
[1] pry(#<MyController>)> request.headers
=> #<ActionDispatch::Http::Headers:0x007fb227cbf490
@env=
{"CONTENT_LENGTH"=>"202",
.
.
.
# omitted headers
.
.
.
"HTTP_X_CSRF_TOKEN"=>"the-correct-token-from-meta-tag",
.
.
.
}
Próbowałem również przekazać token jako klucz z kluczem authenticity_token
(podobnie jak w przypadku formularzy Rails) i ustaw odpowiedni znacznik X-CSRF-Param
(z meta[name="csrf-param"]
).
Jednak ja wciąż się:
Can't verify CSRF token authenticity
Completed 422 Unprocessable Entity in 14638ms
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken
Czy ktoś widział tego wcześniej? Wszelkie przemyślenia na temat tego, co może to spowodować?
Z góry dziękuję!
EDIT:
Po dyskusji w komentarzach odpowiedzi marflar jest, wygląda na to token wygasł, gdy wniosek został złożony (testowane przez porównanie do form_authenticity_token
). To jeszcze bardziej mnie myli, ponieważ token ustawiony w <%= csrf_meta_tags %>
wygasł, gdy pojawi się następne żądanie. Jakieś myśli?
EDIT2: Po rada marflar jest poniżej, dodałem następujące after_filter
do mojego app kontrolera:
def set_csrf_headers
response.headers['X-CSRF-Param'] = request_forgery_protection_token.to_s
response.headers['X-CSRF-Token'] = form_authenticity_token
end
I aktualizowany xhr.onload
w moim metody żądania w następujący sposób:
namespace.request = = function (type, url, opts, callback) {
// code omitted
xhr.onload = function() {
setCSRFHeaders(xhr);
var res = {data: JSON.parse(xhr.response), status: xhr.status};
return callback.call(xhr, null, res);
};
// code omitted
}
function setCSRFHeaders (xhr) {
var csrf_param = xhr.getResponseHeader('X-CSRF-Param');
var csrf_token = xhr.getResponseHeader('X-CSRF-Token');
if (csrf_param) {
document.querySelector("meta[name='csrf-param']").content = csrf_param;
}
if (csrf_token) {
document.querySelector("meta[name='csrf-token']").content = csrf_token;
}
}
I sprawdzeniu, że Nagłówki odpowiedzi, a następnie meta tagi są poprawnie resetowane, jednak do czasu, gdy pojawi się następne żądanie, nowy token wygasa ponownie. Myśli?
Nie jestem pewien, czy rozumiem, co masz na myśli przez "w kodzie HTML" - czy możesz podać mi przykład? – mattmattmatt
@ fancycoder Zaktualizowałem swoją odpowiedź, zastanawiam się, czy możesz użyć nieaktualnego tokena – stephenmurdoch
Właśnie sprawdziłem i masz rację, że jest to nieaktualny token, który niestety pozostawia mnie jeszcze bardziej zdezorientowanego. Metatagów z danymi CSRF ustawia się na początkowym załadowaniu strony, w którym to czasie pasują one do 'form_authenticity_token', ale token jest nieaktualny do czasu wysłania pierwszego żądania ajax. Nie ma więc znaczenia, czy ustawię je w kodzie HTML, czy jako nagłówki, ponieważ wystąpi to w tym samym czasie, a tym samym napotkam ten sam problem z tracącym tokenem przed następnym żądaniem. Dzięki za twoją pomoc - wszelkie pomysły tutaj? – mattmattmatt