[转] 几分钟实现 PHP 登录 QQ,支付宝等网站

原文地址: 几分钟实现 PHP 登录 QQ,支付宝等网站

小记

这一阵在做一个小东西,用 fiddler 抓包分析之后,发现 QQ 旗下的东西只要集成了一键登录的业务,Cookie 里面会有一个登录状态的会话标识 skey,去请求业务的时候带上 skey 就行了。

github 搜索一通,模拟登录 QQ 有 python 实现,V8 解析 JS 的实现。 
https://github.com/LeoHuang2015/qqloginjs

本来作为一个有追求的人,应该自己用 PHP 实现 QQ 登录密码加密过程的,但想到 QQ 登录 JS 改下加密规则,我就要跟着改,太累。我核心需求只是要一个账号的 Cookie 而已,就放弃了,还是以不变应万变吧。

性感的 selenium

最终选择 selenium 来实现,结果使用过程真是不要太爽,几行代码就搞定了。。。感谢 github 上大家的轮子。

使用 FaceBook 家 PHP 驱动 selenium 的包, https://github.com/facebook/php-webdriver

大家如果用到 php-webdriver,有个小细节要注意,

如果报这个错:

The path to the driver executable must be set by the webdriver.chrome.driver system property; for more information, see https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver. The latest version can be downloaded from http://chromedriver.storage.googleapis.com/index.html

要让设置浏览器的驱动程序路径,其实是因为你没有这个驱动,这个不是浏览器,是需要专门下载的。 去https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver  找到 chromedriver 的下载地址  https://sites.google.com/a/chromium.org/chromedriver/downloads

放到 selenium jar 包的同级目录

贴个小代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
namespace App\Helpers;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\WebDriverBy;

class QQHelper
{
static protected $users=[];

static protected $cookieJar;

static protected $host = 'http://localhost:4444/wd/hub';

static protected $driver;

static protected $loginUrl='http://ui.ptlogin2.qq.com/cgi-bin/login?style=9&pt_ttype=1&appid=549000929&pt_no_auth=1&pt_wxtest=1&daid=5&s_url=https%3A%2F%2Fh5.qzone.qq.com%2Fmqzone%2Findex';

static public function login(){

self::$driver = RemoteWebDriver::create(self::$host, DesiredCapabilities::chrome(),5000);
self::$driver->get(self::$loginUrl);
self::$driver->findElement(WebDriverBy::id('guideSkip'))->click();
self::$driver->findElement(WebDriverBy::id("u"))->sendKeys('10000');//账号
self::$driver->findElement(WebDriverBy::id("p"))->sendKeys('password');//密码
self::$driver->findElement(WebDriverBy::id('go'))->click();
self::$cookieJar=self::$driver->manage()->getCookies();

print_r(self::$cookieJar);

//self::$driver->quit();
}
}

演示

小结

selenium 是真真实实开浏览器去浏览,所以并发性能极差,在大规模的场景下是不可以使用的,所以我们要取长补短,用 selenium 突破 JS 实现比较复杂的地方,用 curl,Gouttle,Guzzle,这些东西去实现高并发。

selenium 虽然用法简单,但用处极大,有兴趣的同学可以玩玩。

Web 前端 - 岗位职责

技能要求

Vue/React/Angular 框架中的至少一种

工作职责

• 配合产品经理和设计师快速实现优秀的前端界面

• 持续改进当前产品的前端功能,优化性能,改善访问体验

• 主导前端的设计和开发, 维护, 部署

• 维护伙玩聊天室项目, 网页端项目

岗位要求

• 2 年以上 web 前端开发经验

• 精通 H5、CSS3,JavaScript 基础, 熟悉 Es5/Es6 便捷语法结构

• 使用 js 编写封装良好的前端交互组件, 维护以及优化前端页面性能

• 熟练使用 Vue/React/Angular 至少一种框架使用经验, 对框架的数据管理有自己的应用经验, 对 route/middleware 应用有自己的见解

• 熟悉前后台交互流程, 并有对流程优化的经验

• 熟悉 websocket 以及相关类库

• 具有优秀的团队协作及沟通能力

• 对前端技术有持续的激情,追求最佳用户体验,责任心强,善于学习新事物

• 对 SPA 有 SEO 经验的视为加分项

• 熟练使用 React/Redux 视为加分项

• 有 Npm 包封装经验视为加分项

详细工作内容

  • 保障网页访问是 https 访问, 并且不要出现非安全的资源

学习使用 echo 模块

Nginx echo 模块是在 nginx 程序上扩展了 echo 输出字符的功能,对于调试很方便,项目地址: https://github.com/openresty/echo-nginx-module

安装

目前支持 nginx-1.11.2,高版本可能安装失败,我装 1.11.13 失败了,更多支持 nginx 的版本见: https://github.com/openresty/echo-nginx-module#compatibility

release 下载最新的安装包,并解压.

在配置 Nginx 时用: ./configure --add-module=/你的解压路径,并编译安装,如果是重新编译安装可参考: 重新编译安装

使用

只是研究了一些常用的

echo - 输出字符

  • 语法: echo [options] <string>...
  • 默认值: no
1
2
3
4
5
6
# 简单的hello,world!
server {
location = /api/hello {
echo "hello,world!";
}
}

默认 echo 会自动换行,不需要换行可以: echo -n xxx;;

echo_before_body,echo_after_body - 页面前、后插入内容

  • 语法: echo_before_body [options] [argument]...
  • 默认值: no
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
# 简单的输出
location = /api/hello {
echo_before_body echo_before_body;
echo "hello,world!";
echo_after_body echo_after_body;
}

# 常见于代理页面前、后插内容
location = /api/proxy_before_after {
echo_before_body echo_before_body;
echo_before_body echo_before_body;
proxy_pass http://127.0.0.1;
echo_after_body echo_after_body;
echo_after_body echo_after_body;
}
}

echo_sleep - 请求等待

  • 语法: echo_sleep <seconds>
  • 默认值: no
1
2
3
4
5
6
7
8
9
10
11
server {
# 简单的输出
location = /api/sleep {
echo 1;

# 等待1秒
echo_sleep 1;

echo 2;
}
}

echo_location_async,echo_location - 请求指定路径

  • 语法: echo_location_async <location> [<url_args>]
  • 默认值: no
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
location /main {
# 异步调用/sub
echo_location_async /sub;

echo world;
}

location /main2 {
# 同步调用/sub
echo_location_async /sub;

echo world;
}

location /sub {
echo hello;
}

异步跟同步的区别是:

  1. 异步会并行的去请求
  2. 同步等待当前请求结束才会往下执行

下面这个整个时间为 2s,因为新路径最大是 2s:

1
2
3
4
5
6
7
8
9
10
11
location /main {
echo_location_async /sub1;
echo_location_async /sub2;
echo "took $echo_timer_elapsed sec for total.";
}
location /sub1 {
echo_sleep 2;
}
location /sub2 {
echo_sleep 1;
}

下面这个整个时间为 3s,因为需要等待/sub1完成才进入/sub2:

1
2
3
4
5
6
7
8
9
10
11
location /main {
echo_location /sub1;
echo_location /sub2;
echo "took $echo_timer_elapsed sec for total.";
}
location /sub1 {
echo_sleep 2;
}
location /sub2 {
echo_sleep 1;
}

可以通过第二个参数传querystring: echo_location_async /sub 'foo=Foo&bar=Bar';

echo_foreach_split - 分隔循环

  • 语法: echo_foreach_split <delimiter> <string>
1
2
3
4
5
location /split {
echo_foreach_split ',' $arg_list;
echo "item: $echo_it";
echo_end;
}

上面配置当访问: /split?list=cat,dog,mouse 时会输出:

1
2
3
item: cat
item: dog
item: mouse

$arg_list是对应$args.list

那么配置全echo_location_async可以做成nginx-combo服务了,如:

1
2
3
4
5
6
7
location = /api/combo {
echo_foreach_split ',' $query_string;
echo "/* combo: $echo_it */";
echo_location_async $echo_it;
echo;
echo_end;
}

访问: /api/combo?/a.js,/b.js,需要注意的是文件的路径必须以/开始,因为匹配的location,当然真的 nginx-combo 服务请看: nginx-http-concat

其他变量请去官网查看~