如何使用CURL进行带验证码和会话的登录

16
define('COOKIE', './cookie.txt');
define('MYURL', 'https://register.pandi.or.id/main');
function getUrl($url, $method='', $vars='', $open=false) { // 设置HTTP请求头部 $agents = 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16'; $header_array = array( "Via: 1.1 register.pandi.or.id", "Keep-Alive: timeout=15,max=100", ); static $cookie = false; if (!$cookie) { $cookie = session_name() . '=' . time(); // 如果还没有会话cookie,就创建一个 } $referer = 'https://register.pandi.or.id/main'; // 请求来源URL $ch = curl_init(); if ($method == 'post') { // 如果是POST请求,设置POST参数 curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, "$vars"); } curl_setopt($ch, CURLOPT_HEADER, 1); // 返回HTTP头信息 curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HTTPHEADER, $header_array); // 设置HTTP头信息 curl_setopt($ch, CURLOPT_USERAGENT, $agents); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 把返回的数据存到变量中而不是直接输出 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 5); // 允许跳转(最多5次) curl_setopt($ch, CURLOPT_MAXREDIRS, 10); // 最多允许10次跳转 curl_setopt($ch, CURLOPT_REFERER, $referer); curl_setopt($ch, CURLOPT_COOKIE, $cookie); curl_setopt($ch, CURLOPT_COOKIEJAR, COOKIE); // 把会话cookie存到文件中 curl_setopt($ch, CURLOPT_COOKIEFILE, COOKIE); // 从文件中加载会话cookie curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 不验证SSL证书 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
$buffer = curl_exec($ch); // 执行curl请求 if (curl_errno($ch)) { echo "error " . curl_error($ch); // 如果curl出错,输出错误信息 die; } curl_close($ch); return $buffer; // 返回请求结果 }
function save_captcha($ch) { // 设置HTTP请求头部 $agents = 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16'; $url = "https://register.pandi.or.id/jcaptcha"; static $cookie = false; if (!$cookie) { $cookie = session_name() . '=' . time(); // 如果还没有会话cookie,就创建一个 } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_USERAGENT, $agents); curl_setopt($ch, CURLOPT_COOKIESESSION, true); curl_setopt($ch, CURLOPT_COOKIE, $cookie); curl_setopt($ch, CURLOPT_COOKIEJAR, COOKIE); // 把会话cookie存到文件中 curl_setopt($ch, CURLOPT_COOKIEFILE, COOKIE); // 从文件中加载会话cookie curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); // 返回二进制数据流 $data = curl_exec($ch); // 执行curl请求,获取验证码图片 curl_close($ch); $captcha_tmpfile = './captcha/captcha-' . rand(1000, 10000) . '.jpg'; // 生成临时文件名 $fp = fopen($captcha_tmpfile, 'w'); // 在临时文件中保存验证码图片 fwrite($fp, $data); fclose($fp); return $captcha_tmpfile; // 返回验证码图片的路径 }
if (isset($_POST['captcha'])) { // 如果已经提交了验证码 $id = "yudohartono"; $pw = "mypassword"; $postfields = "navigation=authenticate&login-type=registrant&username=" . $id . "&password=" . $pw . "&captcha_response=" . $_
 <form action='' method='POST'>
        <img src='<?php echo $captcha ?>' />
        <input type='text' name='captcha' value=''>
        <input type='submit' value='proses'>
    </form>";
如果无法读取'cookie.txt'并且无法写入'cookie.txt',则显示"cookie fail to read"。然后将'../pandi/'文件夹的权限设置为'777'。

这是cookie.txt的内容:

# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This file was generated by libcurl! Edit at your own risk.
register.pandi.or.id FALSE / FALSE 0 JSESSIONID 05CA8241C5B76F70F364CA244E4D1DF4

提交表单后显示:

HTTP/1.1 200 OK Date: Wed, 27 Apr 2011 07:38:08 GMT Server: Apache-Coyote/1.1 X-Powered-By: Servlet 2.4; Tomcat-5.0.28/JBoss-4.0.0 (build: CVSTag=JBoss_4_0_0 date=200409200418) Content-Length: 0 Via: 1.1 register.pandi.or.id Content-Type: text/plain X-Pad: avoid browser bug

如果没有错误"Captcha invalid",则一直无法成功登录到pandi。我的脚本出了什么问题?
我不想破解验证码,但我希望能够在我的网页上显示验证码,并让用户从我的网页上输入验证码,使用户可以自动注册dotID域名。

6个回答

21

验证码旨在区分人类和机器人(程序)。看起来你正在使用程序尝试登录。验证码似乎很好地完成了它的工作:)。

我没有看到任何合法的方法可以避开它。


我同意@bazmegakapa的观点 - 但你可能想要阅读一下这个链接http://www.cs.sfu.ca/~mori/research/gimpy/ - Phliplip
我会获取验证码并显示给用户输入,然后进行登录。我这样做是因为我希望我的客户可以自动注册pandi.or.id的域名,并从我的网页上管理他们的域名,因为pandi.or.id没有像其他域名注册商一样的API。 - yudo hartono
我联系了PANDI,他们说他们没有API或转售计划,所以我们必须手动为我们的客户注册域名。 - yudo hartono
@yudo hartono 他们应该给一些线索,你不应该为此打破验证码 :)。 - kapa
3
我们能否保存图片,然后手动输入验证码? - Anggie Aziz
显示剩余2条评论

3
这是因为,您从第一个getURL(即第一个curl_exec)获取了验证码图像并处理了验证码,但要提交您的验证码,您需要getURL(即再次curl_exec),这意味着又到了一个新页面,需要输入一个新的验证码。
因此,您把旧的验证码放在了新的验证码中。我也遇到过同样的问题,并解决了它。

0

验证码是服务器在您访问页面时创建的动态图像。它会不断变化,您必须从页面中提取验证码,然后解析它,最后提交您的登录页面。每当页面被触发加载时,验证码都会随之改变!


0

使用PHP我不知道如何做,你必须获取验证码并找到解决方法。它有很多算法可以为您完成此操作,但如果您想使用Java,我已经从this link中破解了源代码以获取解决验证码的代码,并且对于许多验证码系统它非常有效。

因此,您可以尝试实现自己的验证码解决方案,这将需要很长时间,尝试查找现有的PHP实现,或者,在我看来,最好的选择是使用JDownloader代码库。


0

是的,Andro Selva是正确的。第二个请求会提供新的验证码。一旦使用getUrl函数加载验证码,并且第二次加载是从save_captcha函数进行的,因此这是2个不同的图像。

它必须像这样做: 在关闭curl之前和post之前下载验证码图像,并告诉脚本等待您提供验证码答案-我将使用preg_match。 这也需要一些javascript。

如果验证码图像是通过javascript生成的,则需要使用相同的cookie或令牌执行此javascript。 在这种情况下,更简单的解决方案是使用例如mozila ffox的livehttpheaders插件记录标题。


0

使用无头浏览解决方案是可能的。例如:在Node上使用zombie.js和coffee.js。此外,也可以尝试从验证码中提取“图像”,并使用图像识别技术“读取”图像并将其转换为文本,然后将其与表单一起提交。

截至今天,“欺骗”验证码的唯一可靠方法是使用无头浏览。


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