Как сгенерировать токен CSRF из консоли Rails?

Я пытаюсь сделать аутентифицированный почтовый запрос, и мне нужен CSRF. Когда я вхожу в систему, он почему-то не генерирует _csrf_token:

2.0.0p247 :126 > app.post '/community_members/login', {"refinery_user[login]"=>'chloe', 'refinery_user[password]'=>'test'}
 => 302
2.0.0p247 :127 > app.session
 => {"warden.user.refinery_user.key"=>[[56], "$2a$10$gr/rTcQfuXnes1Zml3qOPu"], "session_id"=>"f77d89cef9ff1710890f575b479bb690"}

Я пробовал app.session[:_csrf_token] ||= SecureRandom.base64(32) перед входом в систему, но он всегда удаляется. Сначала я попытался получить форму входа, но _csrf_token все еще не установлен.

2.0.0p247 :133 > app.get '/community_members/sign_in'
2.0.0p247 :134 > app.response # authenticity_token is burried in the raw HTML
2.0.0p247 :136 > app.post '/community_members/login', {"refinery_user[login]"=>'chloe', 'refinery_user[password]'=>'test'}
2.0.0p247 :137 > app.session
 => {"warden.user.refinery_user.key"=>[[56], "$2a$10$gr/rTcQfuXnes1Zml3qOPu"], "session_id"=>"c2c564229e55b81ca788788558d7d11a"}

Как мне вручную генерировать токен для передачи запроса на отправку?

Ой, я думаю, мне нужно отправить аутентификацию_token (установленную в сеансе после получения формы входа в систему) в форму входа в систему, после чего она помещает ее в сеанс навсегда! Это сработало:

app.post '/community_members/login', {'authenticity_token' = > 'GfT5GtcUmYQ927oNQmh2MR0NKQucGSx8mtMg3Ph9kXw =', "refinery_user [login]" = > 'chloe', 'refinery_user [password]' = > 'test'}

Вот полный пример: qaru.site/questions/16858/...

3 ответа

Мне казалось, что использование Nokogiri для анализа ответа было немного тяжелым, поэтому я написал простое регулярное выражение, чтобы вытащить токен аутентификации из ответа.

app.get '/api_with_form'
authenticity_token = app.response.body.match(/<[^<]+authenticity_token[^>]+value="([^"]+)"[^>]+>/)[1]

Я использую это для входа в систему

app.get '/users/sign_in'
authenticity_token = app.response.body.match(/<[^<]+authenticity_token[^>]+value="([^"]+)"[^>]+>/)[1]
app.post '/users/sign_in', 'user[email]' => 'my_username', 'user[password]' => 'my_password', authenticity_token: authenticity_token


Если вы не загрузите страницу до того, как вы сделаете app.post, на ней не будет создан токен CSRF. Вручную создание нового не поможет, потому что оно не будет соответствовать тому, что хранится на сервере, что может быть некоторым значением null.

Вам нужно загрузить страницу, проанализировать токен CSRF, а затем использовать его.

В качестве альтернативы вы можете загрузить форму, попытаться прочитать токен CSRF из app.session[:_csrf_token] и использовать его.


Я использую эти команды в консоли rails:

app_controller = ActionController::Base::ApplicationController.new
app_controller.request = ActionDispatch::Request.new({})
app_controller.send(:form_authenticity_token)

licensed under cc by-sa 3.0 with attribution.