devise user sign_in дава грешка при удостоверяване за маркер за автентичност на CSRF токен

Използвам devise (най-нова версия - 3.2.0) с rails (най-нова версия - 4.0.1)

Правя просто удостоверяване (без ajax или api) и получавам грешка за CSRF маркер за автентичност. Проверете POST заявката по-долу

started POST "/users/sign_in" for 127.0.0.1 at 2013-11-08 19:48:49 +0530
Processing by Devise::SessionsController#create as HTML

 Parameters: {"utf8"=>"✓",    
 "authenticity_token"=>"SJnGhXXUXjncnPhCdg3muV2GYCA8CX2LVFV78pqddD4=", "user"=> 
{"email"=>"[email protected]", "password"=>"[FILTERED]", "remember_me"=>"0"},
"commit"=>"Sign in"}

Can't verify CSRF token authenticity
 User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."email" =  
'[email protected]' LIMIT 1
(0.1ms)  begin transaction
SQL (0.4ms)  UPDATE "users" SET "last_sign_in_at" = ?, "current_sign_in_at" = ?,
"sign_in_count" = ?, "updated_at" = ? WHERE "users"."id" = 2  [["last_sign_in_at", Fri,
08 Nov 2013 14:13:56 UTC +00:00], ["current_sign_in_at", Fri, 08 Nov 2013 14:18:49 UTC
+00:00], ["sign_in_count", 3], ["updated_at", Fri, 08 Nov 2013 14:18:49 UTC +00:00]]
(143.6ms)  commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 239ms (ActiveRecord: 144.5ms | Search: 0.0ms)

Основният URL адрес сочи към home#new, което е като

class HomeController < ApplicationController
   before_action :authenticate_user!
   def index
   end
end

Генерираният html изглед на страницата за вход е като:

  • мета тагове

    <meta content="authenticity_token" name="csrf-param" />
    <meta content="aV+d7Z55XBJF2VtyL8V3zupR3OwhaQ6UHNtlQLBQf5Y=" name="csrf-token" />
    
  • форма

    <form accept-charset="UTF-8" action="/users/sign_in" class="new_user" id="new_user" 
    method="post">
    <div style="margin:0;padding:0;display:inline">
    <input name="utf8" type="hidden" value="&#x2713;" />
    <input name="authenticity_token" type="hidden
    value="aV+d7Z55XBJF2VtyL8V3zupR3OwhaQ6UHNtlQLBQf5Y=" />
    </div>
    <div><label for="user_email">Email</label><br />
    <input autofocus="autofocus" id="user_email" name="user[email]" type="email" value="" />
    </div>
    
    <div><label for="user_password">Password</label><br />
    <input id="user_password" name="user[password]" type="password" /></div>
    
    <div><input name="user[remember_me]" type="hidden" value="0" />
    <input id="user_remember_me" name="user[remember_me]" type="checkbox" value="1" /> 
    <label for="user_remember_me">Remember me</label></div>
    
    <div><input name="commit" type="submit" value="Sign in" /></div>
    </form>
    

Заявката за удостоверяване дори актуализира стойностите last_sign_in_at и sign_in_count, но когато се опитам да осъществя достъп до current_user в контролера, тя идва като nil.

Според мен това всъщност не е влизане в user. Но тогава идва въпросът "защо се актуализира стойността на last_sign_in_at/sign_in_count в таблицата user?"


person rtcoms    schedule 08.11.2013    source източник
comment
Преди месеци имах подобен проблем и можех да го разреша с: Изтриване на всички бисквитки и кеша в моя браузър. Надявам се, че е и за вас   -  person Flo    schedule 08.11.2013
comment
добре, може и да е така. Нека се опитам.   -  person rtcoms    schedule 08.11.2013
comment
Не работи дори след изчистване на кеша и бисквитките. Дори пробвах в друг браузър.   -  person rtcoms    schedule 08.11.2013
comment
Можете ли да публикувате вашето мнение за страницата за регистрация? И също така има ли „‹%= csrf_meta_tags %›“ във вашия файл application.html.erb?   -  person Philip7899    schedule 11.11.2013
comment
Актуализирах въпроса си с генерирани изгледи html код.   -  person rtcoms    schedule 12.11.2013
comment
Видяхте ли публикациите: stackoverflow .com/questions/7203304/ , stackoverflow.com/questions/11986939/ , stackoverflow.com/questions/15040964/ , stackoverflow.com/questions/9362910/ ?   -  person Малъ Скрылевъ    schedule 13.11.2013
comment
да Те са или за AJAX заявка, или за свързано с api повикване. Моята е проста html заявка, както споменах във въпроса   -  person rtcoms    schedule 13.11.2013
comment
Бихте ли добавили версиите на devise и rails, които използвате за бъдещи читатели на този въпрос?   -  person carols10cents    schedule 14.11.2013
comment
Добавена версия на релси и дизайн   -  person rtcoms    schedule 14.11.2013
comment
Подобен проблем с удостоверяване. Мисля, че можете да проверите тук: stackoverflow.com/a/16264496/1915916   -  person TheAshwaniK    schedule 14.11.2013
comment
Случаят в предоставената връзка е, че заявката е направена чрез curl заявка. В моя случай това е направено чрез формуляр, изобразен от релси.   -  person rtcoms    schedule 14.11.2013


Отговори (4)


Когато CSRF токенът не е правилен, Rails няма да чете или да прави никакви актуализации на сесията. Той все още ще извършва всички други действия, посочени от контролера, което обяснява защо виждате актуализацията на DB, но не сте влезли в системата.

Забелязвам, че authenticity_token във вашия дневник и във вашата страница не съвпадат. Разбирам, че това може да се дължи на факта, че сте уловили различна заявка, но трябва да проверите дали тази на страницата съвпада с тази в дневника за същата заявка. Предполагам също, че използвате правилния маркер във вашия изглед, който генерира различен authenticity_token всеки път, а не просто кодирате твърдо HTML входа.

Виждате ли същия проблем с формуляри, които не са свързани с проектиране? Ако не, като заобиколно решение, можете да изключите действието си от проверката на CSRF със следния код във вашия контролер:

protect_from_forgery except: :sign_in

Шансовете за CSRF атака срещу вашето влизане в действие изглеждат доста далечни (‹-игра на думи) за мен.

Освен това, ако е само с devise, бих ви предложил да подадете проблем с тях, което вече сте направили.

person Jason Barnabe    schedule 16.11.2013
comment
маркерите за автентичност на журнала и формуляра са различни, защото добавих код за частта за изглед/формуляр по-късно към въпроса. Току-що го проверих сега и двете са еднакви, така че мисля, че не трябва да е така за горния проблем - person rtcoms; 16.11.2013

Добавете това към контролера на приложения (това работи на Rails 5)

protect_from_forgery unless: -> { request.format.json? }

Добавете това към Devise SessionController

skip_before_action :verify_authenticity_token, only: [:create]

Опитайте с къдрици

curl -X POST -v -H 'Content-Type: application/json' http://0.0.0.0:3000/users/sign_in -d '{"user" : {"email": "[email protected]", "password": "secret" }}'
person Roberto Brvé    schedule 28.08.2018

Нямаше проблем с разработването на скъпоценен камък. Премахнах скъпоценния камък „rails-api“ и приложението ми започна да работи.

person rtcoms    schedule 06.12.2013
comment
Нямам този Gem, но имам същия проблем - person coorasse; 20.03.2014
comment
Опитайте да премахнете някой друг скъпоценен камък и проверете дали това коригира проблема или не. Сигурен съм, че идва най-вече заради някой друг скъпоценен камък - person rtcoms; 21.03.2014
comment
Бих искал да чуя коя част от rails-api се е намесила в devise и как - person A B; 23.03.2016
comment
Rails 5 има rails-api натив, а сега? =( - person Adriano Resende; 23.03.2016
comment
Това е много стар проблем, нямам налична кодова база, в която се сблъсках с този проблем. Не бих могъл да дам повече подробности за това. - person rtcoms; 24.03.2016

Поправих същия проблем, като премахнах опцията „remote: true“ в изгледа: промених form_for(model, remote: true) на form_for(model)

person guest    schedule 18.09.2017