PHP之CURL实现含有验证码的模拟登录
博主最近在为学校社团写一个模拟登录教务系统来进行成绩查询的功能,语言当然是使用PHP啦,原理是通过php数据传输神器---curl扩展,向学校教务系统发送请求,通过模拟登录,获取指定url下的内容。
在开始实验之前有必要对curl扩展进行一下认识
使用CURL的PHP扩展完成一个HTTP请求的发送一般有以下几个步骤:
1. 初始化连接句柄; # curl_init()
2. 设置CURL选项(关键); # curl_setopt()
3. 执行并获取结果; #curl_exec()
4. 释放VURL连接句柄。 #curl_close()
下面看一个简单的实例
$ch = curl_init(); // 1. 初始化
curl_setopt($ch,CURLOPT_URL,$url); // 2. 设置选项,包括URL
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); //设置选项 , 返回url获取的内容
curl_setopt($ch,CURLOPT_HEADER,0); //设置选项 , 不返回HTTP头部信息
$output = curl_exec($ch); // 3. 执行并获取HTML文档内容
//对获取到的内容进行操作
if($output === FALSE ){
echo "CURL Error:".curl_error($ch);
}
curl_close($ch); // 4. 释放curl句柄
下面是curl_setopt选项的常用选项,在下面的实验中将会用到
CURLOPT_URL 需要获取的URL地址,也可以在 curl_init()函数中设置
CURLOPT_HEADER 不返回HTTP头部信息
CURLOPT_COOKIEJAR 连接结束后保存cookie信息的文件。
CURLOPT_COOKIEFILE 包含cookie数据的文件名
CURLOPT_REFERER 伪造来源
CURLOPT_RETURNTRANSFER 将 curl_exec()获取的信息以文件流的形式返回,而不是直接输出
CURLOPT_POST 设置post提交方式
CURLOPT_POSTFIELDS 传递post内容
现在来开始我们的模拟登录实验吧!
第一步:抓包与分析
工具这里使用到的是谷歌浏览器到的开发者工具,对需要进行模拟登录的教务系统页面进行访问,获取相关信息。
我们分析一下抓取到的请求数据:首先直接访问教务系统网址,则在请求头中则会设置cookie。
通过chrome的开发者工具分析网页的请求信息:
由上面可以看到,当我们第一次访问,和服务器建立起联系时,会获得来一枚session,这枚session是唯一的,如果改变,将会导致此次会话断开,重新开始新的会话,这也是在验证码验证时的一个难点。由JSESSIONID名称的特性,我们知道了教务系统是由JAVA编写的,不管使用什么语言编写,数据交互的本质都没有改变。我们照样将实验进行到底。我们再来看看验证码的请求信息:
由上图可以看到,浏览器分别向教务系统主页面(202.206.xxx.xxx)和验证码页面(ValidateCodeAction.do)发送了请求,得到的SESSION是一样的,这也是会话连通的特点。
由上面的特点知道:想要登录成功,必须先获取登录页面的COOKIES,然后拿着COOKIES找服务器对应的验证码。最后提供服务器需要的全部信息。,这里说明一下,session 的运行依赖 session id,而 session id 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 session_id)也就是为什么我将session看作cookie的原因。希望理解,你们自己看成session也无所谓,个人有个人的不同理解罢了!
好了,现在科普玩了,就开始我们的实验吧!!!
我们先来开始获取验证码页面的cookie操作,然后将获取到的验证码写入文件
<?php
//第一步,配置保存的cookie文件的目录,下面使用的session的获取和验证码页面的cookie没有半毛钱关系,纯属是为了解决高并发问题,防止因为多人访问时,因为cookie文件被重写,导致的登录失败
session_start(); //开启session,
$id=session_id(); //获取当前session的id,这个id是存放在浏览器的本地cookie中的
$_SESSION['id']=$id; //因为这个id的唯一性,可以解决高并发访问时登陆失败的问题
$cookie = dirname(__FILE__) . '/cookie/'.$_SESSION['id'].'.txt'; //cookie文件保存的路径
//开始模拟访问验证码页面,获取其cookie
$verify_code_url = "http://xxx.xxx.xxx.xxx/ValidateCodeAction.do"; //这里是验证码地址
$curl = curl_init(); //初始化句柄
curl_setopt($curl, CURLOPT_URL, $verify_code_url); //设置模拟访问的URL
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie); //保存模拟访问时得到的cookie(关键)
curl_setopt($curl, CURLOPT_HEADER, 0); //不输出头信息
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); //返回文件流
$img = curl_exec($curl); //执行curl
curl_close($curl); //释放资源句柄
$fp = fopen("verifyCode.jpg","w"); //获取到的验证码文件名
fwrite($fp,$img); //写入文件
fclose($fp);
?>
获取到的验证码当然是要放到模拟登录的提交表单中咯。假设数据提交页面是login.php,那么,请将上面的代码放到login.php里面,在
标签的src属性中写入verifyCode.jpg的路径。然后将代码提交到deal.php---模拟登录处理页面中。
先查看教务系统登录界面的源代码,获取表单的name。
然后就是设计模拟登录的页面,我将代码贴出来如下(使用了pintuer的前端框架,需要可以自行下载):
<!DOCTYPE html>
<html lang='zh-cn'>
<head>
<title>登录</title>
<meta charset='utf-8' />
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<link rel='stylesheet' href='pintuer.css'>
</head>
<body>
<h1></h1>
<div class="container-layout">
<div class="line">
<div class="xs12 xm12 xb12">
<div class="panel border-main">
<div class="panel-head border-sub bg-main text-center">登录</div>
<div class="panel-body"> <style type="text/css">
.passcode { position: absolute; right: 0; top: 0; height: 32px; margin: 1px; border-left: solid 1px #ddd; text-align: center; line-height: 32px; border-radius: 0 4px 4px 0; }
</style>
<div align="center">
<form action="deal.php" method="post">
<div class="panel padding" style="text-align: left;">
<div class="text-center">
<br>
<h2><strong>欢迎使用 服务</strong></h2>
</div>
<div class="" style="padding:30px;">
<div class="form-group">
<div class="field field-icon-right">
<input type="text" class="input" name="zjh" placeholder="登录账号" data-validate="required:请填写账号,length#>=5:账号长度不符合要求" />
<span class="icon icon-user"></span>
</div>
</div>
<div class="form-group">
<div class="field field-icon-right">
<input type="password" class="input" name="mm" placeholder="登录密码" data-validate="required:请填写密码,length#>=8:密码长度不符合要求" />
<span class="icon icon-key"></span>
</div>
</div>
<?php
//保存session会话
session_start();
$id = session_id();
$_SESSION['id'] = $id;
// 验证码保存
$cookie_jar = dirname(__FILE__) . '/cookie/'.$_SESSION['id'].'.txt';
$url_img='http://202.206.1.176/validateCodeAction.do?random=0.09896789042747245';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url_img);
curl_setopt($ch,CURLOPT_HEADER,0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1) ;
curl_setopt($ch, CURLOPT_REFERER, 'http://202.206.1.176/');
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_jar);
$img = curl_exec($ch);
curl_close($ch);
$img_code = rand(0,500);
$img_name = 'vcode'.$img_code.'.jpg';
$op_file = fopen('./images/'.$img_name, 'w');
fwrite($op_file,$img);
fclose($op_file);
?>
<div class="form-group">
<div class="field">
<input type="text" class="input" name="v_yzm" placeholder="输入验证码" data-validate="required:请填写右侧的验证码" />
<img src="./images/<?php echo $img_name;?>" width="80" height="32" class="passcode" />
</div>
</div>
<div class="form-group">
<div class="field">
<input class="button button-block bg-main text-big" type='submit' value='立即登录'>
</div>
</div>
</div>
</form>
</div>
</div>
<div class='panel-foot border-sub bg-main text-center'><a class='text-red' target='_blank' href='http://xblogs.cn'>xuthus </a> 版权所有</div>
</div>
</div>
</div>
</div>
</body>
</html>
在模拟登录处理页面deal.php中
重点就是使用上面的验证码页面获取得到的cookie文件,让访问在同一个会话中,否则这样验证码虽然是出来,但这个验证码不属于你,所以在你远程登录时候,验证码永远是错误的,永远登录失败。怎么操作呢?看下面代码:
<?php
session_start();//重点,这个必须要开启,否则验证码cookie文件会出错,在其他页面使用curl来进行同一个会话时,这个也要开起
header("Content-type: text/html; charset=gb2312"); //视学校而定,博主学校是gb2312编码,php也采用的gb2312编码方式
//开始模拟登录
$url = "http://202.206.xxx.xxx";
$cookie = dirname(__FILE__) . '/cookie/'.$_SESSION['id'].'.txt';
$post = "name=xx&pwd=xx&yzm=xx";//具体的表单字段(name,pwd,yzm)需要自己查看网页源代码进行获取,后面的值(xx)自己通过$_POST['']来获取,简化的操作可以通过http_build_query($_POST)来实现
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0); //不自动输出头信息
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); //不自动输出数据
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); //抓取跳转后数据
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie); //这里就是使用验证码cookie文件的地方
curl_setopt($ch, CURLOPT_REFERER, $url); //302跳转需要referer,也可以用来伪装来源
curl_setopt($ch, CURLOPT_POSTFIELDS,$post); //post提交数据
$result=curl_exec($ch);
curl_close($ch);
echo $result; //输出内容,如果返回登录成功的界面,那么恭喜你,操作成功啦!!!没操作成功,那么请看看自己哪里出了错,也可以联系博主,我们共同解决。
登录成功后,就可以进行各项查询操作,你可以新建一个专门的chaxun.php页面,先通过chrome的开发者工具,获取到成绩页面的地址,然后再次使用curl进行获取,比如:
<?php
session_start();//这一步不要忘记了哦
$url = 'http://202.206.xxx.xxx/bxqcjcxAction.do';//本学期成绩
$cookie_jar = dirname(__FILE__) . '/cookie/'.$_SESSION['id'].'.txt';
$ch = curl_init() ;
curl_setopt($ch, CURLOPT_URL,$url) ;
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_REFERER, 'http://202.206.1.176/');
curl_setopt($ch,CURLOPT_COOKIEFILE,$cookie_jar);
$data=curl_exec($ch);
echo $data;//返回查询结果
curl_close($ch);
好了,教程写完了!本人博客http://xblogs.cn
PHP之CURL实现含有验证码的模拟登录的更多相关文章
- 模拟登录神器之PHP基于cURL实现自动模拟登录类
一.构思 从Firefox浏览器拷贝cURL命令(初始页.提交.提交后) 自动分析curl形成模拟登录代码 默认参数:ssl/302/gzip 二.实现 接口 (一)根据curl信息执行并解析结果 p ...
- 使用CURL进行模拟登录
在信息采集的时候,要采集的站点可能需要登录,这样使用简单的采集方式(例如file_get_contents)就无法做到了,我们可以利用PHP的CURL扩展库来进行模拟登录,下面给出代码示例: < ...
- PHP模拟登录并获取数据
cURL 是一个功能强大的PHP库,使用PHP的cURL库可以简单和有效地抓取网页并采集内容,设置cookie完成模拟登录网页,curl提供了丰富的函数,开发者可以从PHP手册中获取更多关于cURL信 ...
- 豆瓣模拟登录(双层html)
一.豆瓣模拟登录(双层html) #!/usr/bin/env python # -*- coding: utf-8 -*- #author tom import time from selenium ...
- ph模拟登录获取信息
cURL 是一个功能强大的PHP库,使用PHP的cURL库可以简单和有效地抓取网页并采集内容,设置cookie完成模拟登录网页,curl提供了丰富的函数,开发者可以从PHP手册中获取更多关于cURL信 ...
- curl 模拟登录微信公众平台带验证码
这段时间一直写个项目, 从切图到前端到后台都要搞定,真tm累. 今天下午手残,不停用错误的密码去模拟登录微信公众平台,结果后来出现验证码,瞬间悲剧(菜鸟从来没搞过带验证码的). 研究了一下,发现其实很 ...
- PHP使用CURL实现对带有验证码的网站进行模拟登录的方法
网上的很多模拟登录程序,大都是通过服务程序apache之类的运行,获取到验证码之后显示在网页上,然后填上再POST出去,这样虽然看起来很友 好,但是既然模拟登录,登录后所干的事情就不一定是短时间完成的 ...
- php通过curl扩展进行模拟登录(含验证码)
以下为本人工作中遇到的需要做的事情,之前也没怎么用过curl,查了好多资料,才稍微弄明白一点:本文所有内容只是自己平日工作的记录,仅供大家参考:<?php/*** 模拟登录*/header(&q ...
- [PHP自动化-进阶]002.CURL模拟登录带有验证码的网站
引言:继前文<模拟登录并采集数据>,大家似乎看不过瘾,这会再出一发,模拟实现带验证码网站的登录. 这篇文章主要介绍了PHP使用CURL实现对带有验证码的网站进行模拟登录的方法,可以帮助读者 ...
随机推荐
- 【Git 系列】一个超好用的命令你会用吗?
stash在英文意思是隐藏.git stash 的作用也是隐藏没完成的代码,防止它干扰别人或者新分支的工作. 一.背景 1.1 我们经常会遇到这样的情况 正在 dev 分支开发新功能,做到一半时有人过 ...
- 数据库学习笔记 - MySQL基础知识
一.数据库基础知识 1.1 Whats's 数据库 数据库(Database,DB):将大量数据保存起来,通过计算机加工而成的可以进行高效访问的数据集合.如:大型-银行存储的信息,小型-电话簿. 数据 ...
- Android学习—下载Android SDK的两种方式
在Android Studio中下载Android SDK的两种方式 Android studio下载地址:http://www.android-studio.org/ 方式一.设置HTTP Prox ...
- 一个初步的lilypond模板
代码文档在下方,涉及了许多基本的文档操作,包括: 1)页面设置,包括纸张大小.页边距 2)段落设置,包括不同内容之间的行距 3)乐谱设置,包括设置谱子大小.谱号.调号.拍号,甚至还有拍号/小节线不可见 ...
- 应用程序池自动停止,事件查看器报错6D000780
20210913 今天中午网站突然报错,后台程序无法访问,503错误. 调查发现"应用程序池"被关闭,但是手动开启后不久,又被关闭. 本地调试没问题,所以一开始怀疑是服务器或者Ng ...
- Kubernetes-网络
前言 本篇是Kubernetes第十一篇,大家一定要把环境搭建起来,看是解决不了问题的,必须实战,此篇文章概念比较多,后续我会继续出一些网络相关实战以及原理探索篇. Kubernetes系列文章: K ...
- java 装饰器模式实现代码
目录 1.实现装饰器模式 1.1.公共接口 1.2.接口实现 1.3.装饰器 1.4.装饰构件 1.5.测试装饰器 上图展示的是io流中的一个装饰者模式的代码结构 1.实现装饰器模式 汽车厂生产汽车实 ...
- JavaWeb 请求转发重定向
请求转发和重定向 request除了可以作为请求对象之外,还可以作为域对象,但是该域对象的取值范围,是一次请求范围之内(浏览器地址栏没有发生跳转访问别的资源) 作用:将servlet中的数据通过req ...
- [NOIP2011 提高组] 观光公交
考虑这类每次都有一类物品贡献相同的物品,求使用了 \(k\) 个物品的最优值,则有考虑考虑贪心. 每次找到一个车到的时间\(>\)最后一个人到的时间,那么找一个覆盖个数最大的地方使用它.
- Codeforces 840C - On the Bench(dp/容斥原理)
Codeforces 题目传送门 & 洛谷题目传送门 这是一道 *2500 的 D1C,可个人认为难度堪比某些 *2700 *2800. 不过嘛,*2500 终究还是 *2500,还是被我自己 ...




