vue 验证码实现
验证码组件实现
使用Vue实现验证码功能可以通过自定义组件完成。以下是一个基于Canvas绘制的图形验证码实现方案:
<template>
<div class="captcha-container">
<canvas ref="canvas" @click="refreshCaptcha"></canvas>
<input v-model="inputCode" placeholder="请输入验证码"/>
</div>
</template>
<script>
export default {
data() {
return {
captchaText: '',
inputCode: ''
}
},
mounted() {
this.generateCaptcha()
},
methods: {
generateCaptcha() {
const canvas = this.$refs.canvas
const ctx = canvas.getContext('2d')
canvas.width = 120
canvas.height = 40
// 生成随机验证码文本
this.captchaText = Math.random().toString(36).substr(2, 6).toUpperCase()
// 绘制背景
ctx.fillStyle = '#f5f5f5'
ctx.fillRect(0, 0, canvas.width, canvas.height)
// 绘制文字
ctx.font = '24px Arial'
ctx.fillStyle = '#333'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
// 添加干扰线
for(let i = 0; i < 5; i++) {
ctx.strokeStyle = this.getRandomColor()
ctx.beginPath()
ctx.moveTo(
Math.random() * canvas.width,
Math.random() * canvas.height
)
ctx.lineTo(
Math.random() * canvas.width,
Math.random() * canvas.height
)
ctx.stroke()
}
// 添加干扰点
for(let i = 0; i < 30; i++) {
ctx.fillStyle = this.getRandomColor()
ctx.beginPath()
ctx.arc(
Math.random() * canvas.width,
Math.random() * canvas.height,
1,
0,
2 * Math.PI
)
ctx.fill()
}
// 绘制文字(最后绘制确保不被覆盖)
ctx.fillText(this.captchaText, canvas.width/2, canvas.height/2)
},
getRandomColor() {
const letters = '0123456789ABCDEF'
let color = '#'
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)]
}
return color
},
refreshCaptcha() {
this.generateCaptcha()
},
validateCaptcha() {
return this.inputCode.toUpperCase() === this.captchaText
}
}
}
</script>
<style>
.captcha-container {
display: flex;
align-items: center;
gap: 10px;
}
canvas {
border: 1px solid #ddd;
cursor: pointer;
}
</style>
短信验证码实现
对于短信验证码功能,通常需要结合后端服务。以下是前端实现逻辑:
<template>
<div class="sms-container">
<input v-model="phone" placeholder="手机号码"/>
<input v-model="smsCode" placeholder="验证码"/>
<button
:disabled="countdown > 0"
@click="sendSmsCode"
>
{{ countdown > 0 ? `${countdown}s后重试` : '获取验证码' }}
</button>
</div>
</template>
<script>
export default {
data() {
return {
phone: '',
smsCode: '',
countdown: 0,
timer: null
}
},
methods: {
async sendSmsCode() {
if (!this.phone) {
alert('请输入手机号码')
return
}
try {
// 调用API发送验证码
const response = await axios.post('/api/send-sms', {
phone: this.phone
})
if (response.data.success) {
this.startCountdown()
} else {
alert(response.data.message)
}
} catch (error) {
alert('发送失败,请稍后重试')
}
},
startCountdown() {
this.countdown = 60
this.timer = setInterval(() => {
this.countdown--
if (this.countdown <= 0) {
clearInterval(this.timer)
}
}, 1000)
},
validateSmsCode() {
return axios.post('/api/verify-sms', {
phone: this.phone,
code: this.smsCode
})
}
},
beforeDestroy() {
clearInterval(this.timer)
}
}
</script>
验证码安全增强
为提高验证码安全性,可考虑以下措施:
- 后端生成验证码并存储于session或redis,前端仅显示
- 增加IP限制,防止频繁请求
- 验证码有效期设置(通常5分钟)
- 图形验证码加入扭曲、旋转等效果防止OCR识别
- 短信验证码加入频率限制(如1条/分钟,5条/天)
验证码自动填充处理
现代浏览器支持验证码自动填充,可通过以下方式优化用户体验:
<input
v-model="captcha"
name="one-time-code"
autocomplete="one-time-code"
inputmode="numeric"
>
无障碍访问
确保验证码组件可被屏幕阅读器识别:
<canvas
ref="canvas"
aria-label="验证码"
role="img"
@click="refreshCaptcha"
></canvas>
以上实现方案可根据实际需求进行调整,图形验证码适合防机器人,短信验证码适合用户身份验证场景。







