前端随机验证

在这里插入图片描述

前言:

  对于一个产品来说,除了自身的功能外,安全性就是另一个关注点了,第一道关卡便是登录验证,除了账号密码的验证外,现在好多网页或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种字体,
   可选角度(不要为难自己开发时的眼睛了😂,我基本不要角度)

以上就是简单的两种前端随机码的生成,有不同的方法,欢迎下方留言讨论!下篇实现简单的拖拽校验

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值