基于vue3及nestjs的图片验证码校验流程

796 阅读1分钟

前端部分

这里用的antd-vue,ui库可以自行选择 codeUrl为后端返回的图片链接 每次点击图片时把时间戳拼接在url后面达到刷新图片的功能(投机取巧) onFinish 提交数据将验证码一并提交

<template>
  <a-form
    :model="formState"
    name="basic"
    :label-col="{ span: 8 }"
    :wrapper-col="{ span: 16 }"
    autocomplete="off"
    @finish="onFinish"
    @finishFailed="onFinishFailed"
  >
    <a-form-item
      label="Username"
      name="username"
      :rules="[{ required: true, message: 'Please input your username!' }]"
    >
      <a-input v-model:value="formState.username" />
    </a-form-item>

    <a-form-item
      label="Password"
      name="password"
      :rules="[{ required: true, message: 'Please input your password!' }]"
    >
      <a-input-password v-model:value="formState.password" />
    </a-form-item>

    <a-form-item
      label="验证码"
      name="text"
      :rules="[{ required: true, message: 'Please input your text!' }]"
    >
      <a-input v-model:value="formState.text" />
      <img @click="resetCode" :src="codeUrl" alt="" />
    </a-form-item>

    <a-form-item :wrapper-col="{ offset: 8, span: 16 }">
      <a-button type="primary" html-type="submit">Submit</a-button>
    </a-form-item>
  </a-form>
</template>
<script setup lang="ts">
import axios from "axios";
import { reactive, ref } from "vue";

interface FormState {
  username: string;
  password: string;
  text: string;
}


const codeUrl = ref<string>("/api/user/code");
const resetCode = () => {
  codeUrl.value = "/api/user/code" + "?" + +new Date();
};


const formState = reactive<FormState>({
  username: "",
  password: "",
  text: "",
});
const onFinish = (values: any) => {
  axios.post("/api/user/create", values).then((res) => {
    console.log(res);
  });
};
const onFinishFailed = (errorInfo: any) => {
  console.log("Failed:", errorInfo);
};

</script>

企业微信20220920-152610@2x.png

后端部分

npm i express-session --save

npm i @types/express-session -D

npm install svg-captcha -S

import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Query,
  Req,
  Res,
} from '@nestjs/common';
import * as svgCaptcha from 'svg-captcha';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { UserService } from './user.service';

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService) {
    console.log(111);
  }
  //利用svg-captcha生成校验码图片并存储在前端session中
  @Get('code')
  createCaptcha(@Req() req, @Res() res) {
    const captcha = svgCaptcha.create({
      size: 4, //生成几个验证码
      fontSize: 50, //文字大小
      width: 100, //宽度
      height: 34, //高度
      background: '#cc9966', //背景颜色
    });
    req.session.code = captcha.text; //存储验证码记录到session
    res.type('image/svg+xml');
    res.send(captcha.data);
  }
  @Post('create')
  createUser(@Req() req, @Body() body) {
    if (
      req.session.code.toLocaleLowerCase() === body?.text?.toLocaleLowerCase() //读取前端传来的验证码和存储的验证码对比
    ) {
      return {
        message: '验证码正确',
      };
    } else {
      return {
        message: '验证码错误',
      };
    }
  }
}