canvas实现验证码组件

验证码的功能是保护登录接口和注册接口不被恶意攻击,防止不法分子通过脚本高频率的调用接口,导致服务器资源被恶意占用。

验证码代码与登录和注册业务代码没有太强的关联性,只需要对外 提供验证码字符,并且将字符绘制到图片中,外部可以通过属性获取验证码字符,将用户输入的验证码和组件返回的验证码进行对比,判断输入的验证码是否正确。

接下来是验证码组件的代码实现:

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
<template>
<div class="img-verify">
<canvas
ref="verify"
:width="width"
:height="height"
@click="handleDraw"></canvas>
</div>
</template>

<script>
import { reactive, onMounted, ref, toRefs } from 'vue'
export default {
setup() {
const verify = ref(null)
const state = reactive({
pool: 'ABCDEFGHIGKLMNOPQRSTUVWXYZ1234567890', // 字符串
width: 120, // 宽度
height: 40, // 高度
imgCode: '' // 画布中验证码的字符串内容
})
onMounted(() => {
state.imgCode = draw()
})
const handleDraw = () => {
state.imgCode = draw()
}
// 生成随机数
const randomNum = (min, max) => {
return parseInt(Math.random() * (max - min) + min)
}
// 生成随机颜色方法
const randomColor = (min, max) => {
const r = randomNum(min, max)
const g = randomNum(min, max)
const b = randomNum(min, max)
return `rgb(${r}, ${g}, ${b})`
}
// 绘制图片验证码方法
const draw = () => {
// 拿到上下文
const ctx = verify.value.getContext('2d')
// 填充随机颜色
ctx.fillStyle = randomColor(180, 230)
// 填充一个矩形 宽 高 外部传进来
ctx.fillRect(0, 0, state.width, state.height)
// 定义一个变量来接受字符串
let imgCode = ''
for (let i = 0; i < 4; i++) {
const text = state.pool(randomNum(0, state.pool.length))
imgCode += text
// 随机设置画布内字符串的字号
const fontSize = randomNum(18, 40)
// 字符串随机旋转的角度
const deg = randomNum(-30, 30)
ctx.font = fontSize + 'px Simhei'
ctx.textBaseline = 'top'
ctx.fillStyle = randomColor(80, 150)
ctx.save()
}
// 随机生成5条干扰线
for (let i = 0; i < 5; i++) {
ctx.beginPath()
ctx.moveTo(randomNum(0, state.width), randomNum(0, state.height))
ctx.lineTo(randomNum(0, state.width), randomNum(0, state.height))
ctx.strokeStyle = randomColor(180, 230)
ctx.closePath()
ctx.stroke()
}
// 随机生成40个干扰的小点
for (let i = 0; i < 40; i++) {
ctx.beginPath()
ctx.arc(
randomNum(0, state.width),
randomNum(0, state.height),
1,
0.2 * Math.PI
)
ctx.closePath()
ctx.fillStyle = randomColor(150, 200)
ctx.fill()
}

return imgCode
}
return {
...toRefs(state),
verify,
handleDraw
}
}
}
</script>
<style>
.img-verify canvas {
cursor: pointer;
}
</style>