Den*_*nde 2 login ruby-on-rails httparty
我正在尝试使用 HTTParty 将用户登录到 Rails 应用程序中。这个想法是发送一个POST请求并用它获取一个会话cookie,然后用这个cookie发送一个GET请求并成功登录:
POST 请求
HTTParty.post('url/login/', basic_auth: {user: 'user', password: 'password'}, follow_redirects: false)
Run Code Online (Sandbox Code Playgroud)
返回
#<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"]}>
Run Code Online (Sandbox Code Playgroud)
我发送 GET 请求
HTTParty.get('url/login/success/', cookie: "6552C1F4FD12D1C5B1D3B42168B9588A.node2")
Run Code Online (Sandbox Code Playgroud)
并得到
#<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"]}>
Run Code Online (Sandbox Code Playgroud)
会话更改且用户未登录。与curl成功登录用户的请求相同。研究表明,这可能并不容易,而且这个解决方案也行不通。
任何想法我做错了什么以及思考的方向?按照此处的建议更改为法拉第?
要使用 HTTParty 登录,您必须查看比 cookie 更多的东西。您也必须查看 CSRF_token。我认为您可以使用 gsub 方法获得authenticity_token,但我尝试过并且创建正则表达式非常困难。所以我使用 Nokogiri 来获取实际存在于登录表单中的令牌。以下是细节,最后我会放上完整的代码。
添加需要的Gems,可以在Gemfile中添加
gem 'httparty'
gem 'nokogiri'
Run Code Online (Sandbox Code Playgroud)
运行bundle install以安装 gem。
要获得 CSRF_token,我们必须获得 sign_in 页面。
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]
Run Code Online (Sandbox Code Playgroud)
通过这种方式,我们得到了 auth_token,它以隐藏字段的形式出现。现在让我们获取 cookie,因为可能需要会话 cookie。
cookie_hash = HTTParty::CookieHash.new
get_response.get_fields('Set-Cookie').each { |c| cookie_hash.add_cookies(c) }
Run Code Online (Sandbox Code Playgroud)
在这里,我们在 session 也存在的情况下获取 cookie。现在是获取最终参数的时候了,然后我们将发送 cookie 和 session 以进行登录
params = {"utf8" => "?", "authenticity_token" => auth_token, "user[email]"=>"user@email.com",·
"user[password]"=>"password"}
params["commit"] = "Login"
Run Code Online (Sandbox Code Playgroud)
现在参数已准备就绪,您可以使用以下 httparty 请求登录并获取 cookie。
response = HTTParty.post("http://localhost:3000/users/sign_in", {:body=>params, headers: {'Cookie' => cookie_hash.to_cookie_string }} )
Run Code Online (Sandbox Code Playgroud)
现在对于其他请求,您可以运行相同的 cookie 方法来取回所有 cookie
cookie_hash = HTTParty::CookieHash.new
get_response.get_fields('Set-Cookie').each { |c| cookie_hash.add_cookies(c) }
Run Code Online (Sandbox Code Playgroud)
要访问其他页面,您可以像我们在上面的示例中所做的那样发送带有 cookie 的请求。请记住,如果您再次使用任何具有表单的页面,您也需要再次获取其 csrf。
response = HTTParty.post("http://localhost:3000/users/other_urls", {headers: {'Cookie' => cookie_hash.to_cookie_string }} )
Run Code Online (Sandbox Code Playgroud)
我试过这段代码,它工作得很好。这是供您使用的完整代码
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
Run Code Online (Sandbox Code Playgroud)