个人解决方案,欢迎批评指正。
在网络上找了几款别人封装好的插件,最后选用vue-puzzle-vcode来实现。具体使用:
npm install vue-puzzle-vcode
代码:
<template>
<Vcode
:show="isShow"
@onSuccess="onSuccess"
@onClose="onClose"
/>
<button @click="onSubmit">登录</button>
</template>
<script>
import Vcode from "vue-puzzle-vcode";
export default {
data(){
return {
isShow: false, // 验证码模态框是否出现
}
},
components:{
Vcode
},
methods:{
onSubmit(){
this.isShow = true;
},
// 用户通过了验证
onSuccess(msg){
this.isShow = false; // 通过验证后,需要手动隐藏模态框
},
// 用户点击遮罩层,应该关闭模态框
onClose(){
this.isShow = false;
}
}
}
</script>
详细用法参考:官方文档
由于这个是纯前端的实现,没有后端校验模块,所以我做了修改。
前后端校验的思路:
后端生成图片拼图位置的X、Y坐标(pinX、pinY),并存入session中,然后将值传给前端。前端以此做相应验证的绘制。然后用户操作后,前端获取用户移动到的最终X坐标(newX)判断验证成功,再将用户移动到的最终X坐标传入后端,后端作为校验依据。
vue-puzzle-vcode插件是随机生成拼图位置的X、Y坐标(pinX、pinY)的,我将组件新增输入参数pinXY=[pinX,pinY]。
修改vue-puzzle-vcode源码app.vue,新增传入参数pinXY,然后把pinX和pinY的赋值部分传修改成pinXY[0] pinXY[1]。最后,新增onSuccess的传出值,把this.newX加上去。然后将this.newX和校验距离x丢到后端接口,后端就以像前台一样的校验方式去通过this.newX计算x,进行校验。
/**
* //后端校验公式
* //session值:pinX pinY
* //传入值newX
*const startWidth=50
* const startX=0
* const canvasWidth=310
* var w = startWidth + newX - startX;
* var styleWidth=w < 50 ? 50 : w > this.canvasWidth ? this.canvasWidth : w;
* var x = Math.abs(
pinX -
(styleWidth - 50) +
20 * ((styleWidth - 50) / (canvasWidth - 50)) -
3
);
x<10 且等于前端传入的x 则成功校验
*/
修改完app.vue记得将cmd运行路径改为vue-puzzle-vcode下,npm install后,在npm run build 重新生成dist下面的文件,才能生效哦。
修改后引用组件:
<template>
<div>
<Vcode
:show="isShow"
:pinXY="pinXY"
:canvasWidth="canvasWidth"
:canvasHeight="canvasHeight"
@onSuccess="onSuccess"
@onClose="onClose"
:imgs="imgs_arr"
/>
<el-button @click="onSubmit">登录</el-button>
</div>
</template>
<script>
import Vcode from "vue-puzzle-vcode";
import imgs_arr from './imgData.js'
export default {
data(){
return {
pinXY:[0,0],
canvasWidth:310,
canvasHeight:160,
imgs_arr,
isShow: false, // 验证码模态框是否出现
}
},
components:{
Vcode
},
methods:{
getPinXY(){
// let pinX=this.getRandom(90, this.canvasWidth - 90);
// let pinY=this.getRandom(20, this.canvasHeight - 90);
//后端以此方式生成
this.pinXY=[pinX,pinY]
console.log('pinxy')
console.log(this.pinXY)
},
// 工具 - 范围随机数
getRandom(min, max) {
return Math.round(Math.random() * (max - min) + min);
},
onSubmit(){
// this.getPinXY();
this.isShow = true;
},
// 用户通过了验证
onSuccess(msg,newX){
//后端校验
this.isShow = false; // 通过验证后,需要手动隐藏模态框
},
// 用户点击遮罩层,应该关闭模态框
onClose(){
this.isShow = false;
},
},
created(){
// this.init()
}
}
</script>