如何从Rails控制台生成CSRF令牌?

时间:2014-05-28 21:18:46

标签: ruby-on-rails csrf refinerycms

我正在尝试进行经过身份验证的帖子请求,我需要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"}

如何手动生成令牌以传递给帖子请求?


哦,好吧,我想我需要在登录表单中提交authenticity_token(在获取登录表单后在会话中设置),然后将其永久地放入会话中!这很有效:

  

app.post' / community_members / login',{' authenticity_token' =>' GfT5GtcUmYQ927oNQmh2MR0NKQucGSx8mtMg3Ph9kXw ='," refinery_user [login]& #34; =>' chloe',' refinery_user [密码]' =>'测试'}

以下是一个完整的示例:https://stackoverflow.com/a/23899701/148844

3 个答案:

答案 0 :(得分:7)

我觉得使用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

答案 1 :(得分:3)

除非您在执行app.post之前加载页面,否则不会生成任何CSRF令牌。手动生成一个新的将无济于事,因为它与服务器上存储的内容不匹配,这可能是一些null值。

您需要加载页面,解析出CSRF令牌,然后使用该令牌。

或者,您可以加载表单,尝试从app.session[:_csrf_token]中读取CSRF令牌并使用它。

答案 2 :(得分:2)

我在rails console中使用这些命令:

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