# 用小程序替代验证码实现人机验证
通常一个网站会使用图片验证码来验证用户是一个真实人类,防止机器人刷服务,薅羊毛,消耗资源。
但随着AI识别能力提高,简单的图片验证码已经很容易被破解,过于复杂的验证码又会让真实用户很难使用。
但是,用户用微信扫码并唤醒小程序这个行为是很难伪造的,因此可以用这个行为来检测用户的真实性。
原理很简单:小程序给网站按需提供不限量的二维码,用户微信扫码唤醒本小程序,本小程序向网站后台发送通知,网站后台授权前端继续提供服务。
除了扫码行为,本验证方案不需要用户做任何其它操作,也无须用户提供任何信息。
而网站需要做的就是在本小程序注册自己的服务,并提供一个回调网址。
人机验证小程序作为基础工具提供免费服务,小程序和后端代码都在此开源。
在线演示:https://myfile.link/mmv/index
实际应用案例:https://myfile.link
# 如何在自己的网站中使用
假设你已经拥有一个网站,并需要验证码服务,只需要三步就可给自己的网站提供人机验证。
## 1 登记网站
请用微信扫码扫码或者搜索人机验证小程序。
![二维码](./qr.png)
打开小程序后,登记自己的网站,也就是提供一个回调url,这个回调url用于接受小程序后台通知网站已经扫码某个二维码。
登记会立时生效,同时你会得到一个skey,用于你的网站后台向程序后台申请二维码。
## 2 调用API申请二维码并在前端展示
每当你需要验证用户的真实性时,在你的网站后台用以下API申请一个二维码
API:https://myfile.link/getcaptcha?skey=xxxx (把xxx替换成你自己的skey)
调用结果:
```JS
{
code:0,
data:{
qrcode, //二维码图像,格式为:"data:image/png;base64,xxxxxx"
captcha //此二维码的扫码值
}
}
```
把二维码发给前端显示
```html
<img src="{{qrcode}}"></img>
```
## 3 处理回调
如果用户拿微信扫了二维码,无须其它操作,微信会调起人机验证小程序,小程序会自动按网站注册的回调url发出通知
假设你注册的回调url为:https://mywebsite.com/captcha,
那么你的网站会收到类似这样的通知:https://mywebsite.com/captcha?code=xxx
其中code就是之前申请二维码时得到的captcha,根据这个captcha你可以认定某二维码已经被真实人类使用,从而授权其所指向的用户可以进行下一步操作
```js
//类似这样
app.get("/captcha", async (req, res) => {
const {code}=req.query
//根据code做something
...
//一定要返回响应信息
res.json({
code:0
})
});
```
请确保你的网站后台正确响应这个回调并返回200,否则小程序后台会按5秒间隔最多通知三次。
# 最佳实践
有图形验证码实践经验的人已经可以根据上述信息重构自己的人机验证系统。
这里给出一些参考代码。
重点是:在前端部分,我们采用长轮询(Long polling)方案,而不是使用setInterval定时询问后端扫码结果,这样可以把询问频度控制在50秒左右,同时用户一旦扫码又能立即通知前端。参考资料:https://zh.javascript.info/long-polling
假设你的前端已经显示二维码,可以用以下代码询问并等待后端通知用户扫码结果:
```js
//util.js
export function waitAuth(md5,n=0) {
let url = _host + `/captcharesult?token=${md5}`
if(n>20)return {
code:1 //二维码超时
}
return new Promise((resolve) => {
var xhr = new XMLHttpRequest()
xhr.open('get', url)
xhr.send()
xhr.onreadystatechange = async function () {
if (this.readyState === 4) {
if(this.status == 502 || this.status==400){
let r = await waitAuth(md5,n+1)
resolve(r)
}
else if (this.status === 200) {
let data = JSON.parse(this.response)
resolve(data)
} else {
console.log("captcharesult err:", this.response)
await new Promise(rs => setTimeout(rs, 1000));
let r = await waitAuth(md5,n+1);
resolve(r)
}
}
}
})
}
//index.js
//其它业务逻辑
...
let r = await util.waitAuth(md5)
if(r.code==1){
this.$msgbox({
title: "提示",
message: '人机验证二维码超时,请重试'
})
this.qrcode = ''
this.bShowCaptcha = false
return
}
//扫码验证通过,用户可进行下一步操作
...
```
现在转到后端,假设你已经申请到二维码,并把它保存到一个列表_captchaList里等待用户扫码
```js
_captchaList.push({
md5, //二维码的MD5,我们可以把这个给前端,让它作为询问结果的凭据
scene, //二维码的具体内容
state: 0, //验证结果0=未验证,1=验证成功
t: Date.now()
})
```
处理前端发来的轮询:
```js
app.get("/captcharesult", async (req, res) => {
const { token } = req.query //二维码的MD5
console.log("captcharesult token:", token)
let bHas = _captchaList.some( (item) => {
if (item.md5 == token) {
return true
}
})
if(!bHas){
return res.json({
code: 1, //code=1 我们用这个通知前端需要重新获取二维码认证
result: 0
})
}
//长轮询方案就是一直等用户扫码直到连接超时断连
req.on('close', function() {
_captchaList.some((item,index) => {
if (item.md5 == token) {
if(item.resolve){
item.resolve(0)
item.resolve=null
}
//_captchaList.splice(index,1) 不能删除,因为客户端会重新发起连接询问
return true
}
})
});
//在这等着扫码验证,连接超时关闭客户端会重新发
//console.log("等待扫码验证")
let r = await new Promise(resolve=>{
_captchaList.some( (item) => {
if (item.md5 == token) {
item.resolve=resolve
return true
}
})
})
//console.log("扫码验证完成:",r)
if(r==0)return //表示连接超时断连,不处理
if(r==-1){ //二维码超时则通知前端刷新二维码
return res.json({
code: 1, //code=1表示刷新
result: 0
})
}
//这里已经扫码成功,用户可以实现其它业务逻辑,比如myfile.link同时进行对象存储授权
/*
console.log("开始对象存储授权")
let result = await tencent.TencentCosAuth(token)
console.log("对象存储授权结果:",!!result)
if(!result){
return res.json({
code: 0,
result: 0
})
}
*/
return res.json({//通知前端验证成功,并且附上其它继续操作所需数据
code: 0,
result: 1,
data:result
})
});
```
当然后端还需要处理人机验证小程序发来的回调,假设你注册的回调为:htts://mysite.com/captcha
那么你可以这样处理回调:
```js
app.get("/captcha", async (req, res) => {
const { code } = req.query
let r = _captchaList.some((item) => {
if (item.scene == token) {
item.state = 1 //验证通过
return true
}
})
return res.send({
code: 0,
data: '验证成功'
});
});
```
你可能注意到处理回调时,只是简单改变了state的状态,并没有调用resolve,这是因为我们建议在一个全局setInterval函数里处理:
```js
setInterval(()=>{
let timestamp = Date.now()
for(let i=_captchaList.length-1; i>=0; i--){ //倒序遍历方便删除操作
let item = _captchaList[i]
if(item.state){
if(item.resolve){
item.resolve(1)
item.resolve = null
}
//_captchaList.splice(i,1)
}
else if (item.t + 600000 < timestamp) {//超时10分钟删除
if(item.resolve)item.resolve(-1)
_captchaList.splice(i, 1)
没有合适的资源?快使用搜索试试~ 我知道了~
用微信扫码唤醒小程序的方式来实现人机验证.zip
共132个文件
js:48个
map:36个
json:13个
需积分: 5 0 下载量 4 浏览量
2024-08-15
13:49:51
上传
评论
收藏 6.35MB ZIP 举报
温馨提示
项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松copy复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全栈开发),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助 【资源内容】:项目具体内容可查看/点击本页面下方的*资源详情*,包含完整源码+工程文件+说明(若有)等。【若无积分,此资源可私信获取】 【本人专注IT领域】:有任何使用问题欢迎随时与我联系,我会及时解答,第一时间为您提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【适合场景】:相关项目设计中,皆可应用在项目开发、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面中 可借鉴此优质项目实现复刻,也可基于此项目来扩展开发出更多功能 #注 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担 2. 部分字体及插图等来自网络,若是侵权请联系删除,本人不对所涉及的版权问题或内容负法律责任。收取的费用仅用于收集和整理资料耗费时间的酬劳
资源推荐
资源详情
资源评论
收起资源包目录
用微信扫码唤醒小程序的方式来实现人机验证.zip (132个子文件)
app.d23bbf2850eb3fd81898150d5a4e1ec7.css 271KB
app.ebdcb59afba2a6e10871a646a7677054.css 271KB
app.65e13aba3ba32cd3b0c8a10600c7b78a.css 271KB
app.ea0c2ccb605cb7f2b095486060ffeada.css 271KB
app.7508738e9bb36dbe003c5dba24cf56ce.css 271KB
app.9231cd2137e5848a9f8af5addf2490f4.css 271KB
app.9968311ab0461ea6731deaf4fc9e0140.css 271KB
app.1c0f8e9f791e6859287de6e6dc85be5d.css 271KB
app.9e98ed6840341023ee742529c66170e0.css 270KB
app.7d379650ccf8cd600d8bbcbac377f053.css 270KB
Dockerfile.development 601B
Dockerfile 1KB
.dockerignore 83B
.gitignore 2KB
.gitignore 79B
captchatest.html 10KB
index.html 1KB
favicon.ico 4KB
favicon.ico 4KB
vendor.3e19e7f9d2f82f764dd9.js 949KB
vendor.1efcb8c1bdfbdc1f96f9.js 890KB
vendor.ef0130c9a94be7ec2c73.js 690KB
app.1246424d8dfc2e4bbd4d.js 15KB
app.a01362a7bb30c89d5a13.js 15KB
app.8884df6e7c3af0885419.js 15KB
app.926dd574faa9497756fb.js 15KB
app.88f48924ab88dab516b9.js 15KB
app.e7285f983e136b9c3077.js 15KB
app.8907b3d4de44966abdcf.js 15KB
app.55803916bc0a9517f000.js 15KB
app.8b2c9d38a6b30f289010.js 14KB
app.961e1bafcb4ea8cda4ca.js 14KB
app.8e527d9fab24cc38fc4a.js 14KB
app.3cbcb33f1923a50f37a9.js 14KB
app.9c830ad198a3e6ff08dc.js 14KB
app.ec190a20a2e33b85e39c.js 14KB
app.412c1d1daf16f6ab9b3f.js 14KB
app.9dab099adae70a2c65ec.js 14KB
app.01119c32fc85178e1064.js 14KB
app.de3fa07bf1d7af102bff.js 14KB
app.be84918b78b4d0e24fbe.js 14KB
app.07fe39060cf4cc8c54cc.js 14KB
app.89623ca1585ceb310305.js 14KB
app.d2a8692a9ebaf0c62954.js 14KB
app.aa6b366a73856c690cf5.js 14KB
app.570e28d5f7e11eca8ddb.js 14KB
app.81d0198765e42be3bf00.js 14KB
app.edc2b52ca0de1e1dc7f3.js 14KB
app.f55d02967f7bdf6b72d3.js 13KB
app.1468a5b9aec540989e0a.js 13KB
app.9b691fbec56155b2a484.js 13KB
app.cee3085dc699dcc4ede4.js 13KB
app.9ceaa394a74af0d894b0.js 13KB
index.js 12KB
db.js 7KB
app.c7b7fe3f851979ae9cd5.js 5KB
tencentcos.js 5KB
register.js 4KB
getqrcode.js 2KB
index.js 2KB
result.js 1KB
manifest.2ae2e69a05c33dfc65f8.js 857B
callback.js 829B
.eslintrc.js 587B
util.js 460B
app.js 168B
tempCodeRunnerFile.js 135B
package-lock.json 131KB
project.config.json 1KB
package-lock.json 874B
container.config.json 718B
app.json 658B
project.private.config.json 636B
package.json 574B
package.json 266B
sitemap.json 191B
register.json 71B
project.config.json 37B
index.json 27B
result.json 27B
LICENSE 1KB
vendor.3e19e7f9d2f82f764dd9.js.map 6.47MB
vendor.1efcb8c1bdfbdc1f96f9.js.map 6.05MB
vendor.ef0130c9a94be7ec2c73.js.map 4.47MB
app.a01362a7bb30c89d5a13.js.map 117KB
app.1246424d8dfc2e4bbd4d.js.map 117KB
app.e7285f983e136b9c3077.js.map 117KB
app.88f48924ab88dab516b9.js.map 117KB
app.8884df6e7c3af0885419.js.map 117KB
app.926dd574faa9497756fb.js.map 116KB
app.8907b3d4de44966abdcf.js.map 116KB
app.55803916bc0a9517f000.js.map 116KB
app.8b2c9d38a6b30f289010.js.map 115KB
app.961e1bafcb4ea8cda4ca.js.map 115KB
app.3cbcb33f1923a50f37a9.js.map 115KB
app.9c830ad198a3e6ff08dc.js.map 114KB
app.ec190a20a2e33b85e39c.js.map 114KB
app.8e527d9fab24cc38fc4a.js.map 114KB
app.412c1d1daf16f6ab9b3f.js.map 113KB
app.9dab099adae70a2c65ec.js.map 113KB
共 132 条
- 1
- 2
资源评论
热爱技术。
- 粉丝: 2424
- 资源: 7862
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功