我该如何在Rails控制台中生成一个CSRF令牌?

5

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

我该如何手动生成令牌以传递给POST请求?
哦,好的,我认为我需要提交authenticity_token(在GET登录表单后设置的)到登录表单,然后它会永久地将其放入会话中! 这个方法可以解决问题:
app.post '/community_members/login', {'authenticity_token'=>'GfT5GtcUmYQ927oNQmh2MR0NKQucGSx8mtMg3Ph9kXw=', "refinery_user[login]"=>'chloe', 'refinery_user[password]'=>'test'}
这里有一个完整的示例:https://dev59.com/qHVC5IYBdhLWcg3w51hv#23899701
3个回答

9

我觉得使用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
非常感谢您! - knagode

3

我在Rails控制台中使用以下命令:

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

3
除非您在执行app.post之前加载页面,否则根本不会生成CSRF令牌。手动生成新令牌也无济于事,因为它与存储在服务器上的令牌不匹配,后者很可能是一些null值。
您需要加载页面,解析CSRF令牌,然后使用该令牌。
或者,您可以加载表单,尝试从app.session [:_csrf_token]中读取CSRF令牌并使用它。

即使我先获取登录表单,然后提交,session[:_csrf_token] 也没有被设置。 - Chloe
我必须将authenticity_token作为登录的一部分提交! - Chloe
1
@Chloe,我猜你的意思是你意识到需要先加载登录页面,然后获取令牌? - merlin2011

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接