SAE禁止了本地的IO操作,所以在使用上需要单独修改下代码!做过小偷程序或者模拟登录时,我想很多童鞋都用过curl函数。SAE已经完全兼容curl函数(内部用FetchURL实现)。在使用curl发送http请求时,附带cookie却有些头疼了。下面讲讲个人的思路,如果有更好的方案,欢迎补充~
首先我在自己的网站做了个php脚本,需要接受两个通过post发送的字段,username为admin,password为123456,当用户名和密码正确显示"已登录",并给COOKIE随便赋一些值,如果没有接收到数据或数据错误显示“未登录”,如果已登录,存在session的时候则显示“admin”,并打印COOKIE数组。
我现在的需求是,在a.php中使用curl发送相应的字段模拟登录,保存cookie文件,并输出请求到的内容,在b.php中使用a.php保存的cookie文件请求(不发送任何数据)并输出请求到的内容。
在本地的理论效果是,a.php中输出的内容是“已登录”,而b.php则应输出“admin”和cookie数组的内容:
a.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<?
$cookie_file=realpath('login.tmp');
//保存cookie信息的文件绝对路径
$post_fields="username=admin&password=123456";
//要发送的字段内容
$ch=curl_init("http://xxx.com/login.php");
curl_setopt($ch,
CURLOPT_HEADER,0);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_USERAGENT,"Mozilla/5.0
(compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
curl_setopt($ch,CURLOPT_NOPROGRESS,0);
curl_setopt($ch,
CURLOPT_FOLLOWLOCATION,
1);
curl_setopt($ch,CURLOPT_COOKIEJAR,$cookie_file);
//将cookie保存在文件中
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$post_fields);
echo
$data=curl_exec($ch);
curl_close($ch);
?>
|
b.php
1
2
3
4
5
6
7
8
9
10
11
12
|
<?
$cookie_file=realpath('login.tmp');
//保存cookie信息的文件绝对路径
$ch=curl_init("http://xxx.com/login.php");
curl_setopt($ch,
CURLOPT_HEADER,0);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_USERAGENT,"Mozilla/5.0
(compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
curl_setopt($ch,CURLOPT_NOPROGRESS,0);
curl_setopt($ch,
CURLOPT_FOLLOWLOCATION,
1);
curl_setopt($ch,CURLOPT_COOKIEFILE,$cookie_file);
//使用a.php中保存的cookie信息
echo
$data=curl_exec($ch);
curl_close($ch);
?>
|
但是这段代码在SAE上就无法实现效果,因为SAE不允许IO操作。下面给出两种方案解决这种问题!
第一种,使用kvdb服务,讲cookie信息从http头中提取出来,通过字符串的形式发送。
a.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<?
$ch=curl_init("http://xxx.com/login.php");
$post_fields="username=admin&password=123456";
//要发送的字段内容
curl_setopt($ch,
CURLOPT_HEADER,1);
//需要接收http头的内容
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_USERAGENT,"Mozilla/5.0
(compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
curl_setopt($ch,CURLOPT_NOPROGRESS,0);
curl_setopt($ch,
CURLOPT_FOLLOWLOCATION,
1);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$post_fields);
$data=curl_exec($ch);
curl_close($ch);
$TempArr
= explode("\r\n\r\n",
$data);
$TeData
= '';
//存放cookie信息
while(
preg_match("/(.*?)Set\-Cookie: (.*?); (.*)/is",
$TempArr[0],
$matches)
){
$TeData
.=
$matches[2].";";
//将http头中的cookie信息匹配出来并存入字符串中
$TempArr[0]
= $matches[3];
}
file_put_contents('saekv://login.tmp',$TeData);
//将cookie信息保存到kvdb中
?>
|
使用KVDB服务需要先开启,此部分建议看下官方文档,这里为了简便使用了Wrappers,建议使用原生的接口对kvdb进行操作!
b.php
1
2
3
4
5
6
7
8
9
10
11
12
|
<?
$cookie=file_get_contents('saekv://login.tmp');
//将cookie信息从kvdb取出来
$ch=curl_init("http://xxx.com/login.php");
curl_setopt($ch,
CURLOPT_HEADER,0);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_USERAGENT,"Mozilla/5.0
(compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
curl_setopt($ch,CURLOPT_NOPROGRESS,0);
curl_setopt($ch,
CURLOPT_FOLLOWLOCATION,
1);
curl_setopt($ch,CURLOPT_COOKIE,$cookie);
//讲cookie信息以字符串的方式发送
echo
$data=curl_exec($ch);
curl_close($ch);
?>
|
第二种方法是,使用TmpFS服务,将cookie写入临时文件中,由于临时文件的生存周期等同于php请求,所以我们需要把临时文件的内容保存到KVDB中,然后在其他脚本使用时,再将cookie信息写入临时文件中供curl调用!
a.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<?
$cookie_file=SAE_TMP_PATH
.'login.txt';
//保存cookie信息的临时文件路径
$post_fields="username=admin&password=123456";
//要发送的字段内容
$ch=curl_init("http://xxx.com/login.php");
curl_setopt($ch,
CURLOPT_HEADER,0);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_USERAGENT,"Mozilla/5.0
(compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
curl_setopt($ch,CURLOPT_NOPROGRESS,0);
curl_setopt($ch,
CURLOPT_FOLLOWLOCATION,
1);
curl_setopt($ch,CURLOPT_COOKIEJAR,$cookie_file);
//将cookie保存在文件中
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$post_fields);
echo
$data=curl_exec($ch);
curl_close($ch);
$cookie=file_get_contents($cookie_file);
file_put_contents('saekv://login.tmp',$cookie);
//将cookie信息保存到kvdb中
?>
|
b.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?
$cookie=file_get_contents('saekv://login.tmp');
$cookie_file=SAE_TMP_PATH
.'login.txt';
//保存cookie信息的临时文件路径
file_put_contents($cookie_file,$cookie);
//将kvdb中的cookie信息保存到临时文件中
$ch=curl_init("http://xxx.com/login.php");
curl_setopt($ch,
CURLOPT_HEADER,0);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_USERAGENT,"Mozilla/5.0
(compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
curl_setopt($ch,CURLOPT_NOPROGRESS,0);
curl_setopt($ch,
CURLOPT_FOLLOWLOCATION,
1);
curl_setopt($ch,CURLOPT_COOKIEFILE,$cookie_file);
//使用a.php中保存的cookie信息
echo
$data=curl_exec($ch);
curl_close($ch);
?>
|
总结下:
第一种方法效率相对高些,但是通过正则匹配获得的cookie信息,有一定的准确性问题。
第二种方法效率要低不少,因为进行很多次的IO操作,但是保存了比较好的原生特性。
(以上对KVDB的操作都是用Wrappers的方式,大家可以考虑使用使用原生接口。)