AnyProxy 知识点
2017年07月12日
终端输入以下命令可以启用 AnyProxy ,-i
参数的意思时启用 HTTPS 传输模式
sudo anyproxy -i
HTTP 通信过程的各个阶段进行抽离,分解成三个阶段:
- 收到来自客户端请求之后,允许开发者直接从本地提供返回
- 在转发请求到服务器前,允许开发者对发送的请求进行修改
- 在收到服务器响应之后,允许开发者对响应内容进行修改,再返回给客户端
对于上述每个阶段,AnyProxy 都提供了 API 接口,引入开发者编写自己的规则代码,实时干预通信过程,以此满足各类自定义需求。
具体提供的接口包括:
- 收到用户请求之后
- shouldUseLocalResponse ,是否在本地直接发送响应(不再向服务器发出请求)
- dealLocalResponse 如果 shouldUseLocalResponse 返回 true,会调用这个函数来获取本地响应内容(异步接口)
- 向服务端发出请求之前
- replaceRequestProtocol 替换向服务器发出的请求协议,支持 http 和 https 的替换
- replaceRequestOption 替换向服务器发出的请求参数,即 nodeJS 中的 request option
- replaceRequestData 替换请求的 body
- 向用户返回服务端的响应之前
- replaceResponseStatusCode 替换服务器响应的 http 状态码
- replaceResponseHeader 替换服务器响应的 http 头
- replaceServerResDataAsync 替换服务器响应的数据(异步接口)
- pauseBeforeSendingResponse 在请求返回给用户前的延迟时间
可以通过查看/usr/local/lib/node_modules/anyproxy/rule_sample
熟悉对应的规则。
解析 HTTPS
AnyProxy 解析 HTTPS 的原理是自制根证书(rootCA),待终端信任这份证书之后,再用它签发各个域名的二级证书,此时二级证书可以重新对各个页面进行解析。这种方案和 HTTPS 的“中间人攻击”(MITM)是一致的。
所以此证书是需要先安装的。安装参考:http://anyproxy.io/cn.html#osx 系统信任 ca 证书
更多参考网址:
- https://github.com/alibaba/anyproxy
- https://github.com/alibaba/anyproxy/wiki/%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%9A%84%E6%96%B0%E8%BD%AE%E5%AD%90%EF%BC%9Aanyproxy
- https://github.com/alibaba/anyproxy/wiki/HTTPS%E7%9B%B8%E5%85%B3%E6%95%99%E7%A8%8B
- https://github.com/alibaba/anyproxy/wiki/What-is-rule-file-and-how-to-write-one
- https://github.com/alibaba/anyproxy/issues/20
微信查看历史消息程序中的知识点总结
判断一些网页请求
1// 通过Request头部accept判断请求的文件类型是否为图片 2if (/image/.test(req.headers.accept)) { 3 // 返回本地图片 4 callback(200, { 'content-type': 'image/png' }, fs.readFileSync('/Users/liqiang/Desktop/1.png')); 5} 6 7// 判断url时 8/profile_ext/.test(req.url); // 历史消息页 9/getappmsgext/.test(req.url); // 阅读量和点赞量的url
rule_default.js
在shouldUseLocalResponse
这个接口中编写拦截代码,只让属于微信的Request
请求通过,屏蔽其他网页和图片请求。具体代码如下:
1// 屏蔽除微信外其他网络连接 2if (/[weixin|wx].qq.com/.test(req.headers.host)) { 3 // 历史消息抓取完成之后由发出的Ajax请求 4 if ('/startAnother' == req.url) { 5 return true; 6 } else { 7 return false; 8 } 9} else { 10 return true; 11}
在dealLocalResponse
中不做任何反应,这样来自客户端的请求就不会无限发出了。当然需要对之后发出的 Ajax 请求作出回应:
1if (req.url == '/startAnother') { 2 // 调用打印PDF的程序接口 3 myRule.toPdf(); 4 callback(200, { 'content-type': 'text/plain' }, ''); 5}
通过上面的两个接口,就可以只让微信的请求真正的发出去。然后接收到的响应数据便可以通过replaceServerResDataAsync
此接口来提取历史文章链接,以及注入返回至微信客户端的自动翻页 js 代码。
1replaceServerResDataAsync: function(req,res,serverResData,callback){ 2 3 // 历史消息页判断,调用自己写的规则 4 if (/profile_ext.+__biz/.test(req.url)){ 5 myRule.getProfile(req,res,serverResData,callback); 6 } else { 7 callback(serverResData); 8 } 9 10},
此时便引用到了myRule
此模块文件了。前提是需要在开头通过require
来引用:
1var myRule = require('./myRule');
myRule.js
此文件中导出了两个方法,可以在上面文件引用:
1exports.getProfile = getProfile; 2exports.toPdf = toPdf;
getProfile
方法即通过分析Response
数据,提取历史文章的链接,然后保存在文本文件中。具体细节部分:
- 判断 Response 为 json 还是 html ,然后根据对应的文件提取目标数据
- 第一次返回的 html 文件提取完目标之后,还需要注入一段 js 代码,实现自动翻页功能和加载全部完成后发出 Ajax 请求的功能
- 发出 Ajax 的请求便会依次通过
shouldUseLocalResponse
接口和dealLocalResponse
接口,继而调用下面的toPdf
方法
toPdf
方法是提取完成后,发出调用直接爬虫的程序请求。