ruby-on-rails - 使用 HTTParty 传递 cookie
问题描述
我正在尝试使用 HTTParty 将用户登录到 Rails 应用程序。这个想法是发送一个 POST 请求并用它获取一个会话 cookie,然后用这个 cookie 发送一个 GET 请求并成功登录:
POST 请求
HTTParty.post('url/login/', basic_auth: {user: 'user', password: 'password'}, follow_redirects: false)
返回
#<HTTParty::Response:0x7f9c71bc4598 parsed_response=nil, @response=#<Net::HTTPFound 302 302 readbody=true>, @headers={"date"=>["Mon, 04 Mar 2019 08:02:26 GMT"], "server"=>["Apache"], "strict-transport-security"=>["max-age=31536000"], "set-cookie"=>["JSESSIONID=6552C1F4FD12D1C5B1D3B42168B9588A.node2; Path=/; Secure; HttpOnly"], "x-content-type-options"=>["nosniff"], "x-xss-protection"=>["1; mode=block"], "cache-control"=>["no-cache, no-store, max-age=0, must-revalidate"], "pragma"=>["no-cache"], "expires"=>["0"], "location"=>["/ipad-api/v20/login/failure/"], "vary"=>["Accept-Encoding,User-Agent"], "content-length"=>["20"], "connection"=>["close"], "content-type"=>["text/plain; charset=UTF-8"]}>
我发送一个 GET 请求
HTTParty.get('url/login/success/', cookie: "6552C1F4FD12D1C5B1D3B42168B9588A.node2")
并得到
#<HTTParty::Response:0x7f9c71b95950 parsed_response={"head"=>{"apikey"=>nil, "sessionid"=>"320E4C622043566D5424627BDE11997D.node3", "timestamp"=>1551686567666, "sessiontimeout"=>1551689267666, "wishlistItemsCount"=>0, "basketItemsCount"=>0, "loggedIn"=>false, "role"=>"G"}, "data"=>{"user"=>{"profile"=>{"title"=>nil, "firstname"=>nil, "lastname"=>nil, "street"=>nil, "street2"=>nil, "postalcode"=>nil, "city"=>nil, "customerID"=>nil, "customerType"=>0}}, "abandonedBasket"=>false}, "messages"=>[{"code"=>"bmd.api.login.success", "statusCode"=>200, "description"=>"OK"}]}, @response=#<Net::HTTPOK 200 200 readbody=true>, @headers={"date"=>["Mon, 04 Mar 2019 08:02:47 GMT"], "server"=>["Apache"], "strict-transport-security"=>["max-age=31536000"], "set-cookie"=>["JSESSIONID=320E4C622043566D5424627BDE11997D.node3; Path=/; Secure; HttpOnly"], "x-content-type-options"=>["nosniff"], "x-xss-protection"=>["1; mode=block"], "cache-control"=>["no-cache, no-store, max-age=0, must-revalidate"], "pragma"=>["no-cache"], "expires"=>["0"], "vary"=>["Accept-Encoding,User-Agent"], "connection"=>["close"], "transfer-encoding"=>["chunked"], "content-type"=>["application/json;charset=UTF-8"]}>
会话更改并且用户未登录。curl
成功登录用户的相同请求。研究表明,这可能并不容易,而且这种解决方案也不起作用。
任何想法我做错了什么以及思考的方向是什么?按照这里的建议更改为法拉第?
解决方案
要使用 HTTParty 登录,您必须查看比 cookie 更多的东西。你也必须看到 CSRF_token 。我认为您可以使用 gsub 方法获取authentity_token,但我尝试过,创建正则表达式非常困难。所以我使用 Nokogiri 来获取实际存在于登录表单中的令牌。以下是详细信息,最后,我将放置整个代码。
添加所需的 Gems,可以在 Gemfile 中添加
gem 'httparty'
gem 'nokogiri'
运行bundle install
以安装 gem。
要获取 CSRF_token,我们必须获取登录页面。
url = "http://localhost:3000/users/sign_in"
get_response = HTTParty.get(url)
noko_doc = Nokogiri::HTML(get_response)
auth_token = noko_doc.css('form').css('input[name="authenticity_token"]').first.values[2]
这样我们就得到了 auth_token,它的形式是隐藏字段。现在让我们获取 cookie,因为会话 cookie 可能需要。
cookie_hash = HTTParty::CookieHash.new
get_response.get_fields('Set-Cookie').each { |c| cookie_hash.add_cookies(c) }
在这里,我们正在获取会话也存在的 cookie。现在是时候获取最终参数了,然后我们将发送 cookie 和会话来登录
params = {"utf8" => "✓", "authenticity_token" => auth_token, "user[email]"=>"user@email.com",·
"user[password]"=>"password"}
params["commit"] = "Login"
现在参数已准备就绪,您可以使用以下 httparty 请求登录并获取 cookie。
response = HTTParty.post("http://localhost:3000/users/sign_in", {:body=>params, headers: {'Cookie' => cookie_hash.to_cookie_string }} )
现在对于其他请求,您可以运行相同的 cookie 方法来取回所有 cookie
cookie_hash = HTTParty::CookieHash.new
get_response.get_fields('Set-Cookie').each { |c| cookie_hash.add_cookies(c) }
要访问其他页面,您可以使用 cookie 发送请求,就像我们在上面的示例中所做的那样。请记住,如果您再次使用任何具有表单的页面,您也需要再次获取它的 csrf。
response = HTTParty.post("http://localhost:3000/users/other_urls", {headers: {'Cookie' => cookie_hash.to_cookie_string }} )
我尝试了这段代码,它运行良好。这是供您使用的完整代码
require 'httparty'
require 'Nokogiri'
require 'Pry'
url = "http://localhost:3000/users/sign_in"
get_response = HTTParty.get(url)
noko_doc = Nokogiri::HTML(get_response)
auth_token = noko_doc.css('form').css('input[name="authenticity_token"]').first.values[2]
cookie_hash = HTTParty::CookieHash.new
get_response.get_fields('Set-Cookie').each { |c| cookie_hash.add_cookies(c) }
params = {"utf8" => "✓", "authenticity_token" => auth_token, "user[email]"=>"user@example.com",·
"user[password]"=>"password"}
params["commit"] = "Login"
response = HTTParty.post("http://localhost:3000/users/sign_in", {:body=>params, headers: {'Cookie' => cookie_hash.to_cookie_string }} )
puts response
推荐阅读
- php - 在 php 中获得与 Rfc2898DeriveBytes 在 c# 中给出的相同响应
- python - 如何在keras中获取卷积层的特征图
- python - 使用 List Comprehension 和/或 map 避免嵌套 for 循环
- openid-connect - Keycloak:在 JSON 中获取授权码?
- c - 交换数组中最后一次出现的最小值和最大值
- go - Go 中的 Print 和 Printf 有何不同?
- javascript - 在另一个点的对面找到一个点
- php - 自动生成 $_POST 变量
- mqtt - Seedstack - 添加用户和密码的 MQTT 附加组件问题
- sql - 简单查询不支持声明 SQL 构造或语句