前言:
对于一个产品来说,除了自身的功能外,安全性就是另一个关注点了,第一道关卡便是登录验证,除了账号密码的验证外,现在好多网页或App上,还有其他的验证方式,拖拽验证、验证码验证等等,本节主要来一套颜色的验证码验证…
对于前端开发来说,这个工作是后端完成的,但是,在自己的项目中,我们可以放到本地前端校验一次,这样能减少服务器的压力(前端自己的项目,本地一般没有服务器)
所谓随机验证码,无非是随机数据、随机字体、随机角度、随机颜色的任意组合的展示(vue3为例)
第一种:没遮挡物的
<template>
<div id="random-container" @click.stop="refreshValue">
<span v-for="(item,index) in value" :key="index" :style="{color: colorList[index],fontFamily: fontFamilyList[index],transform: 'rotate('+degList[index]+'deg)'}">{{item}}</span>
</div>
</template>
<script setup lang="ts">
import {onMounted, ref} from "vue";
const value = ref('')
const colorList = ref([])
const fontFamilyList = ref(['symbol6','bradhitc','vladlmir','ravie','huawen','magnetob']) // 字体
const degList = ref([])
/**
* 刷新验证码
*/
const refreshValue = () => {
value.value = randomCode(4)
}
/**
* 生成min到max之间的随机整数
* @param min
* @param max
*/
const randomInt = (min:number, max:number) => {
return Math.round(Math.random() * (max - min)) + min;
}
/**
* 随机颜色
*/
let randomColor = () => {
let col = "#";
let str = "0123456789AaBbCcDdEeFf"; // 0-15
for (let i = 0; i < 6; i++) {
let index = randomInt(0, 15);
col += str[index];
}
return col;
}
/**
* 生成N位随机验证码
* @param num
*/
const randomCode = (num:number) => { // num 表示需要几位数的code就传几
let code = "";
for (let i = 0; i < num; i++) {
do {
var ascii = randomInt(48, 122); // 48-122
} while (
(ascii >= 58 && ascii <= 64) || (ascii >= 91 && ascii <= 96)
);
code += String.fromCharCode(ascii);
colorList.value.push(randomColor()) // 随机颜色
degList.value.push(randomInt(0, 45)) // 随机角度
}
return code;
}
onMounted(()=> {
refreshValue()
})
</script>
<style scoped lang="scss">
#random-container{
border: 1px solid #f6f6f6;
display: flex;
align-items: center;
justify-content: center;
width: 120px;
height: 40px;
background: gainsboro;
font-size: 20px;
cursor: pointer;
}
</style>
第二种:canvas 绘制干扰点干扰线
<template>
<div id="random-container" @click="createdCode">
<canvas id="s-canvas" :width="props.contentWidth" :height="props.contentHeight"></canvas>
</div>
</template>
<script lang="ts" setup>
import {onMounted, ref, getCurrentInstance, defineProps} from "vue";
const {proxy} = getCurrentInstance()
const props = defineProps({
fontSizeMin: {
type: Number,
default: 25
},
fontSizeMax: {
type: Number,
default: 30
},
backgroundColorMin: {
type: Number,
default: 255
},
backgroundColorMax: {
type: Number,
default: 255
},
colorMin: {
type: Number,
default: 0
},
colorMax: {
type: Number,
default: 160
},
lineColorMin: {
type: Number,
default: 100
},
lineColorMax: {
type: Number,
default: 255
},
dotColorMin: {
type: Number,
default: 0
},
dotColorMax: {
type: Number,
default: 255
},
contentWidth: {
type: Number,
default: 120
},
contentHeight: {
type: Number,
default: 34
}
})
const identifyCode = ref('') // 验证码初始化
/**
* 生成N个随机数
*/
const randomCode = () => {
const len = 6 // 验证码长度
const codeList = []
const chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz0123456789'
const charsLen = chars.length
for (let i = 0; i < len; i++) {
codeList.push(chars.charAt(Math.floor(Math.random() * charsLen)))
}
identifyCode.value = codeList.join('')
proxy.$emit('getIdentifyCode', identifyCode.value.toLowerCase())
createPic()
}
/**
* 绘制图片
*/
const createPic = () => {
const canvas = document.getElementById('s-canvas')
const ctx = canvas?.getContext('2d')
ctx.textBaseline = 'bottom'
// 绘制背景
ctx.fillStyle = randomColor(props.backgroundColorMin, props.backgroundColorMax)
ctx.fillRect(0, 0, props.contentWidth, props.contentHeight)
// 绘制文字
for (let i = 0; i < identifyCode.value.length; i++) {
createText(ctx, identifyCode.value[i], i)
}
createLine(ctx)
createDot(ctx)
}
/**
* 生成一个随机数
* @param min
* @param max
*/
const randomInt = (min: number, max: number) => {
return Math.floor(Math.random() * (max - min) + min)
}
/**
* 生成一个随机的颜色
* @param min
* @param max
*/
const randomColor = (min: number, max: number) => {
const r = randomInt(min, max)
const g = randomInt(min, max)
const b = randomInt(min, max)
return 'rgb(' + r + ',' + g + ',' + b + ')'
}
/**
* 绘制干扰线
* @param ctx
*/
const createLine = (ctx: any) => {
for (let i = 0; i < 5; i++) {
ctx.strokeStyle = randomColor(props.lineColorMin, props.lineColorMax)
ctx.beginPath()
ctx.moveTo(randomInt(0, props.contentWidth), randomInt(0, props.contentHeight))
ctx.lineTo(randomInt(0, props.contentWidth), randomInt(0, props.contentHeight))
ctx.stroke()
}
}
/**
* 绘制干扰点
* @param ctx
*/
const createDot = (ctx: any) => {
for (let i = 0; i < 80; i++) {
ctx.fillStyle = randomColor(0, 255)
ctx.beginPath()
ctx.arc(randomInt(0, props.contentWidth), randomInt(0, props.contentHeight), 1, 0, 2 * Math.PI)
ctx.fill()
}
}
/**
* 绘制文字
* @param ctx
* @param txt
* @param i
*/
const createText = (ctx: any, txt: any, i: any) => {
ctx.fillStyle = randomColor(props.colorMin, props.colorMax)
ctx.font = randomInt(props.fontSizeMin, props.fontSizeMax) + 'px SimHei'
const x = (i + 1) * (props.contentWidth / (identifyCode.value.length + 1))
const y = randomInt(props.fontSizeMax, props.contentHeight - 5)
const deg = randomInt(-45, 45)
// 修改坐标原点和旋转角度
ctx.translate(x, y)
ctx.rotate(deg * Math.PI / 180)
ctx.fillText(txt, 0, 0)
// 恢复坐标原点和旋转角度
ctx.rotate(-deg * Math.PI / 180)
ctx.translate(-x, -y)
}
onMounted(() => {
randomCode()
})
</script>
<style scoped lang="scss">
#random-container {
height: 38px;
cursor: pointer;
}
</style>
注意:组成一般主要包括:
数据4-6位、
颜色、
1-2种字体,
可选角度(不要为难自己开发时的眼睛了😂,我基本不要角度)
以上就是简单的两种前端随机码的生成,有不同的方法,欢迎下方留言讨论!下篇实现简单的拖拽校验