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实现对带有验证码的网站进行模拟登录的方法,可以帮助读者 ...
随机推荐
- eclipse调试时出现source not found怎么办
调试时遇到source not found,可以点击下方的edit source lookup按钮,进行调试项目的增加 进入后点击ADD按钮 选择java project类型的项目,如图 选择需要调试 ...
- 到底谁才需要Service Mesh?
本文是Service Mesh系列第1篇 随着云原生时代的来临,使用微服务架构的朋友们开始听到一个新的技术名词--Service Mesh(现在来说已经不算新了). 对于一项新技术的学习,总归绕不过两 ...
- java-TCP协议发送和接收数据
TCP协议接收数据的步骤: A:创建接收数据的Socket对象 创建对象的时候要指定端口 B:监听客户端连接 等待客户端连接 C:获取Socket对象的输入流(字节流) D:读数据,并显示在控制台 E ...
- [atARC101F]Robots and Exits
每一个点一定匹配其左边/右边的第一个出口(在最左/右边的出口左/右边的点直接删除即可),否则记到左右出口的距离分别为$x_{i}$和$y_{i}$ 令$p_{i}$表示$i$匹配的出口(左0右1),结 ...
- 【Tool】JDK8 安装
JDK8 2019-07-26 14:05:21 by冲冲 1. 下载 通常前往官网 https://www.oracle.com/technetwork/java/javase/download ...
- 洛谷 P6295 - 有标号 DAG 计数(生成函数+容斥+NTT)
洛谷题面传送门 看到图计数的题就条件反射地认为是不可做题并点开了题解--实际上这题以我现在的水平还是有可能能独立解决的( 首先连通这个条件有点棘手,我们尝试把它去掉.考虑这题的套路,我们设 \(f_n ...
- Codeforces 1396D - Rainbow Rectangles(扫描线+线段树)
Codeforces 题面传送门 & 洛谷题面传送门 一道鸽了整整一年的题目,上一次提交好像是 2020 年 9 月 13 日来着的(?) 乍一看以为第 2 个提交和第 3 个提交只差了 43 ...
- 洛谷 P7154 - [USACO20DEC] Sleeping Cows P(dp)
Portal 题意: 给出两个序列 \(a_1,a_2,\dots,a_n\),\(b_1,b_2,\dots,b_n\),\(i\) 与 \(j\) 能匹配当且仅当 \(a_i\leq b_j\). ...
- CF932F Escape Through Leaf
CF932F Escape Through Leaf 首先, $ O(n^2) $ dp 是很显然的,方程长这样: \[dp[u] = min\{dp[v] + a_u\times b_v\} \] ...
- Codeforces 1332G - No Monotone Triples(数据结构综合)
Codeforces 题目传送门 & 洛谷题目传送门 首先打表即可发现对于任意长度 \(\ge 5\) 的序列总存在一个 Monotone triple,证明不会实在不行直接 \(5^5\) ...




