![仅限 http 标头通信?- 请解释一下?](https://linux22.com/image/504681/%E4%BB%85%E9%99%90%20http%20%E6%A0%87%E5%A4%B4%E9%80%9A%E4%BF%A1%EF%BC%9F-%20%E8%AF%B7%E8%A7%A3%E9%87%8A%E4%B8%80%E4%B8%8B%EF%BC%9F.png)
下面的屏幕截图是使用 firebug 制作的。捕获的 Firefox <-> Web 服务器通信发生在单击登录按钮之后。但我在 Firefox 中看不到任何重定向。这是否意味着 Firefox 和 Web 服务器进行了通信仅在 http 标头级别?
我已经用 ruby/mechanize 编写了脚本,用于从论坛中抓取一些详细信息。我使用以下代码对其进行了测试/编码:维基百科论坛。然后我设法登录我的测试论坛,并愉快地使用正确的论坛完成我的脚本。但我无法登录。我的脚本只返回登录页面,我认为这是“登录尝试失败”。
有人可以向我解释一下下面的截图吗?
- 具体来说,为什么有 11 行?为什么不只有一行?
- 如果我只能理解
blindly/without thinking
对 Web 服务器的回复,对吗?
当我单击登录按钮时,firefox 会发送帖子,
auth_username=myusername&auth_password=mypassword&auth_login=Login
但是我的脚本会发送,auth_username=radek&auth_password=mypassword
这样可以吗,还是&auth_login=Login
必须显示该部分?有没有机会用 ruby 来模拟这种通信?
或者我在想我是否可以
record
沟通然后replay
在我的脚本中(如果可能的话)
登录页面的 html
<form class="login" method="post"> <fieldset>
<legend>Members Login</legend>
<div>
<label for="auth_username">Username</label> <input id="auth_username" name="auth_username">
</div>
<div>
<label for="auth_password">Password</label> <input id="auth_password" name="auth_password" type="password">
</div>
</fieldset>
<div class="buttons">
<input name="auth_login" type="submit" value="Login"><p class="note"><a href="/forgotpassword">Forgot your password?</a></p>
</div>
</form>
我的 ruby 脚本
require 'rubygems'
require 'mechanize'
#agent = WWW::Mechanize.new
agent = WWW::Mechanize.new
page = agent.get("http://www.vbulletin.org/forum/index.php")
login_form = page.form_with(:action => 'login.php?do=login')
puts
login_form.fields.each { |f| puts "#{f.name} : #{f.value}" }
login_form['vb_login_username'] = 'user name'
login_form['vb_login_password'] = ''
page = agent.submit login_form
output = File.open("login.html", "w") {|f| f.write(page.parser.to_html) }
从无效的登录尝试中机械化日志
INFO -- : Net::HTTP::Get: /login?auth_successurl=http://www.somedomain.com/forum/yota?baz_r=1
DEBUG -- : request-header: accept-language => en-us,en;q=0.5
DEBUG -- : request-header: connection => keep-alive
DEBUG -- : request-header: accept => */*
DEBUG -- : request-header: accept-encoding => gzip,identity
DEBUG -- : request-header: user-agent => WWW-Mechanize/0.9.3 (http://rubyforge.org/projects/mechanize/)
DEBUG -- : request-header: accept-charset => ISO-8859-1,utf-8;q=0.7,*;q=0.7
DEBUG -- : request-header: host => www.somedomain.com
DEBUG -- : request-header: keep-alive => 300
DEBUG -- : Read 400 bytes
DEBUG -- : Read 1424 bytes
DEBUG -- : Read 2448 bytes
DEBUG -- : Read 3211 bytes
DEBUG -- : response-header: vary => Accept-Encoding
DEBUG -- : response-header: cache-control => no-store, no-cache, must-revalidate, post-check=0, pre-check=0
DEBUG -- : response-header: connection => close
DEBUG -- : response-header: expires => Thu, 19 Nov 1981 08:52:00 GMT
DEBUG -- : response-header: content-type => text/html; charset=utf-8
DEBUG -- : response-header: date => Fri, 29 Jan 2010 23:43:12 GMT
DEBUG -- : response-header: content-encoding => gzip
DEBUG -- : response-header: server => Apache/2.2.3 (CentOS)
DEBUG -- : response-header: content-length => 3211
DEBUG -- : response-header: set-cookie => PHPSESSID=7cfilg86ju2ldcgso22246hpu4; path=/, WebStats:visitorId=lSMkcwuSWEE%3D; expires=Mon, 27-Jan-2020 23:43:12 GMT; path=/, WebStats:sessionId=%2B2HHK296t%2BQ%3D; expires=Mon, 27-Jan-2020 23:43:12 GMT; path=/
DEBUG -- : response-header: accept-ranges => bytes
DEBUG -- : response-header: pragma => no-cache
DEBUG -- : gunzip body
DEBUG -- : saved cookie: PHPSESSID=7cfilg86ju2ldcgso22246hpu4
DEBUG -- : saved cookie: WebStats:visitorId=lSMkcwuSWEE%3D
DEBUG -- : saved cookie: WebStats:sessionId=%2B2HHK296t%2BQ%3D
INFO -- : status: 200
DEBUG -- : query: "auth_username=radek&auth_password=mypassword"
INFO -- : Net::HTTP::Post: /login?auth_successurl=http://www.somedomain.com/forum/yota?baz_r=1
DEBUG -- : request-header: accept-language => en-us,en;q=0.5
DEBUG -- : request-header: connection => keep-alive
DEBUG -- : request-header: accept => */*
DEBUG -- : request-header: accept-encoding => gzip,identity
DEBUG -- : request-header: content-type => application/x-www-form-urlencoded
DEBUG -- : request-header: user-agent => WWW-Mechanize/0.9.3 (http://rubyforge.org/projects/mechanize/)
DEBUG -- : request-header: cookie => WebStats:sessionId=%2B2HHK296t%2BQ%3D; WebStats:visitorId=lSMkcwuSWEE%3D; PHPSESSID=7cfilg86ju2ldcgso22246hpu4
DEBUG -- : request-header: referer => http://www.somedomain.com/login?auth_successurl=http://www.somedomain.com/forum/yota?baz_r=1
DEBUG -- : request-header: accept-charset => ISO-8859-1,utf-8;q=0.7,*;q=0.7
DEBUG -- : request-header: content-length => 43
DEBUG -- : request-header: host => www.somedomain.com
DEBUG -- : request-header: keep-alive => 300
DEBUG -- : Read 650 bytes
DEBUG -- : Read 1674 bytes
DEBUG -- : Read 2698 bytes
DEBUG -- : Read 3211 bytes
DEBUG -- : response-header: vary => Accept-Encoding
DEBUG -- : response-header: cache-control => no-store, no-cache, must-revalidate, post-check=0, pre-check=0
DEBUG -- : response-header: connection => close
DEBUG -- : response-header: expires => Thu, 19 Nov 1981 08:52:00 GMT
DEBUG -- : response-header: content-type => text/html; charset=utf-8
DEBUG -- : response-header: date => Fri, 29 Jan 2010 23:43:13 GMT
DEBUG -- : response-header: content-encoding => gzip
DEBUG -- : response-header: server => Apache/2.2.3 (CentOS)
DEBUG -- : response-header: content-length => 3211
DEBUG -- : response-header: accept-ranges => bytes
DEBUG -- : response-header: pragma => no-cache
DEBUG -- : gunzip body
INFO -- : status: 200
答案1
重定向通常通过 HTTP 响应状态代码 301(永久移动)或 302(找到/暂时移动)实现。 用于执行重定向的 301 和 302 HTTP 响应状态代码包含在 HTTP 标头中。
仅仅因为您“没有看到 Firefox 中的任何重定向”并不意味着重定向没有发生:它确实在幕后发生了。
有其他在页面中使用 JavaScript 进行重定向。使用 JavaScript,重定向可以对用户显而易见,用户可以先看到一个页面,然后重定向(可能经过延迟)到另一个位置。但是,这些不是通过 HTTP 标头响应状态代码进行传输的 HTTP 重定向。
回答您关于 Ruby 的问题:您应该在 Stack Overflow 上提出该问题。但简而言之,是的,您应该能够使用任何服务器端 Web 技术设置 301 和 302 重定向响应代码。
更新:为了回答您以下评论中的进一步问题:
如果你想进一步了解 HTTP 的工作原理,那么我推荐下面这本书: HTTP:权威指南(作者:David Gourley 和 Brian Totty)。您还可以查阅官方 HTTP 标准,其定义如下RFC 2616:超文本传输协议--HTTP/1.1。
至于为什么你问题中的上述一系列请求需要 11 个步骤,您需要询问相关软件的原作者。它可能可以用更少的步骤来实现,但可能不止 1 个步骤。考虑一下,服务器至少需要一次重定向来在用户的浏览器中设置 cookie,然后再将其发送到受保护的资源。
由于您正在尝试复制基于 cookie 的自定义身份验证机制,因此我还建议您重点研究此类系统通常是如何构建的。
如果您尝试编写登录页面脚本,则应确保您的程序发布到服务器的内容在各个方面都与实际请求相匹配,包括您当前未包含的参数。
此外,你需要确保你的代码是接受并发回服务器发送的任何 cookie。 不保留服务器发送的 cookie 是此类练习中常见的错误。此外,您需要指示用于 HTTP 通信的任何库按照重定向。其中一些默认不遵循重定向。
最后,为了进行调试,从网页和程序中捕获请求和响应的标头和正文,并进行比较. 对任何差异保持怀疑。