我想使用 php CURL 脚本登录一个网站,但它在最后一步被重定向到一个循环中。
我在使用 Firefox 和 Internet Explorer 时使用 Fiddler 来捕获 HTTP 请求和响应。我重新创建了脚本中的步骤。
该网站有几个步骤,包括 302 重定向、在表单提交之前设置 cookie 以及位置重定向。
这一切都进行得很顺利,直到最后一步。该网站加载以下内容。
HTTP/1.1 200 OK
Connection: Keep-Alive
Server: Microsoft-IIS/5.0
Date: Sun, 12 Aug 2012 15:51:55 GMT
X-Powered-By: ASP.NET
Set-Cookie: SMSESSION=*omitted by me*; path=/; domain=website.com
Content-Length: 511
Content-Type: text/html
Set-Cookie: BIGipServerPortal_80_Green=3741601290.20480.0000; expires=Sun, 12-Aug-2012 17:51:57 GMT; path=/
Cache-Control: private
X-PvInfo: [S10201.C29051.A26868.RA0.G7175.U147B7189].[OT/html.OG/pages]
Vary: Accept-Encoding, User-Agent
Content-Encoding: gzip
<!--START:INC\common\include.asp-->
<!--START:INC\common\errorfns.asp-->
<!--END:INC\common\errorfns.asp--><!--START:INC\common\newconstant.asp-->
<!--END:INC\common\newconstant.asp--><!--START:INC\common\securityfns.asp-->
<!--END:INC\common\securityfns.asp--><!--START:INC\common\newptintllocales.asp-->
<!--END:INC\common\newptintllocales.asp-->
<!--START:INC\common\newptintl.asp-->
<!--END:INC\common\newptintl.asp-->
<!--START:INC\common\newutility.asp-->
<!--END:INC\common\newutility.asp-->
<!--END:INC\common\include.asp--><!--START:INC\sso\vendors\ActiveDirectoryServer.asp-->
<!--END:INC\sso\vendors\ActiveDirectoryServer.asp--><!--START:INC\sso\vendors\netegrity.asp-->
<!--END:INC\sso\vendors\netegrity.asp--><!--START:INC\sso\vendors\oblix.asp-->
<!--END:INC\sso\vendors\oblix.asp-->
<!--START:INC\sso\vendors\securant.asp-->
<!--END:INC\sso\vendors\securant.asp--><!--START:INC\sso\vendors\Tivoli.asp-->
<!--END:INC\sso\vendors\Tivoli.asp-->
<!--START:INC\sso\vendors\customsso.asp-->
<!--END:INC\sso\vendors\customsso.asp-->
<!--START:INC\sso\ssoutility.asp-->
<!--END:INC\sso\ssoutility.asp-->
<!--START:INC\sso\sso.asp-->
<HTML>
<BODY onload="javascript:void(document.dologin.submit())">
<FORM ACTION="../admin/dologin.asp" METHOD="POST" NAME="dologin">
<INPUT TYPE="HIDDEN" NAME="RedirectURL" VALUE="">
<INPUT TYPE="HIDDEN" NAME="ssoMode" VALUE="1">
</FORM>
</BODY>
</HTML>
<!--END:INC\sso\sso.asp-->
当 Firefox 提交此表单时,它会被重定向到正确的内容。但是我的 CURL 脚本被重定向到同一页面,但表单输入现在将 RedirectURL 值设置为admin/login.asp?Mode=1
<HTML>
<BODY onload="javascript:void(document.dologin.submit())">
<FORM ACTION="../admin/dologin.asp" METHOD="POST" NAME="dologin">
<INPUT TYPE="HIDDEN" NAME="RedirectURL" VALUE="/admin/login.asp?Mode=1">
<INPUT TYPE="HIDDEN" NAME="ssoMode" VALUE="1">
</FORM>
</BODY>
</HTML>
我使用 Fiddler 复制和粘贴浏览器和 CURL 的执行,并逐行比较它们。两者都发送相同的信息,我没有错过任何 cookie。
我能看到的唯一区别是发送的标头的顺序和发送的 COOKIES 的顺序。
我已经调整了我的 CURL 以发送与 firefox 相同的标题,但我无法获得相同的顺序。
火狐头
GET https://www.website.aa.com/ HTTP/1.1
Host: www.website.com
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:14.0) Gecko/20100101 Firefox/14.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
卷曲头
GET /login/SMLogin.jsp? HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:14.0) Gecko/20100101 Firefox/14.0.1
Host: www.website.com
Accept-Encoding: gzip, deflate
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Connection: keep-alive
最大的区别是 CURL 在 HOST: 之前发送 User-Agent: 和 Accept-Encoding: 的顺序不同。我试图通过以不同的顺序设置 CURL 选项来重新排列事物,但似乎无法获得与 Firefox 相同的顺序。
这是我的 CURL 选项。(我省略了选择 GET 或 POST 并创建查询字符串的步骤)
//process the header
$headerArray = array();
$headerArray[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
$headerArray[] = 'Accept-Language: en-us,en;q=0.5';
$headerArray[] = 'Connection: keep-alive';
if($ref != ""){
$headerArray[] = 'Referer: ' . $ref;
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray) ;
// set up the cURL resource
curl_setopt($ch, CURLOPT_TIMEOUT, CURL_TIMEOUT); // Timeout
curl_setopt($ch, CURLOPT_USERAGENT, WEBBOT_NAME); // Webbot name
curl_setopt($ch, CURLOPT_ENCODING, "gzip, deflate");
// SSL SECTION
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
curl_setopt($ch, CURLOPT_CAINFO, getcwd() . '\cert\ca-bundle.crt');
// Cookie management.
curl_setopt($ch, CURLOPT_COOKIEJAR, COOKIE_FILE);
curl_setopt($ch, CURLOPT_COOKIEFILE, COOKIE_FILE);
curl_setopt($ch, CURLINFO_HEADER_OUT, TRUE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_URL, $target);
另一个区别是发送 cookie 的顺序。由于我让 CURL 处理 cookie 管理,我无法控制顺序。除非我自己管理 cookie 并使用CURLOPT_COOKIE
选项设置它们,但这似乎很痛苦。
那么,是否很可能是标头的顺序和/或发送的 COOKIES 的顺序告诉服务器我的脚本不是真正的浏览器并将我从受保护的内容中重定向?如果是这样,我该如何改变?还是我错过了其他东西?
编辑 这是@MARC_B 评论“javascript 设置cookies”说明了一切。
是的,我了解 CURL 不执行 javascript。我已经查看了 javascript 并复制了脚本中的操作。在提交登录表单后的一个页面上,javascript 验证用户名,然后设置一个 cookie。
if (validate) {
document.cookie = "loggedIn=yes";
document.Login.submit();
}
所以在检索到页面后,脚本将上面的cookie写入cookie文件。
$handle = fopen("cookies.txt", "a");
$cookie = "website.com FALSE /login/ FALSE 0 loggedIn yes";
fwrite($handle, $cookie);
fclose($handle);
其他 javascript 操作只是自动提交表单,它只需要执行 CURL 来复制。
我已经取得了进展。经过一整天的谷歌搜索,我发现其中一个网络表单是CA Siteminder软件的一部分,用于保护资源。链接文档显示表单收集正在使用的浏览器。代理名称在表单中被加密(不确定为什么需要)。我找不到任何关于为什么浏览器很重要的文档。我想知道加密字符串是从 agentname 标头创建的,还是通过使用发送的标头名称的组合和顺序创建的。
我开始脚本时没有设置 cookie。在逐行审查响应标题后,我专注于 2 个特定的 cookie。从未在响应中设置 2 个 cookie 中的脚本 1 的每次运行。但如果每次都不一样。
我决定使用 Firefox 登录时显示的所有 cookie 设置 cookie 文件。这一次,脚本在上述页面循环一次后继续进入新页面。新页面包含检测浏览器类型和设置的 JavaScript。分析页面需要一段时间。
所以答案似乎是我错过了几个必要的 cookie 中的一个。
如果有人能对 Siteminder 生态系统和典型的 asp 登录脚本有所了解,我想听听。