koa+node+redis实现注册图片验证码功能

基本思路

  1. 设计图片验证码获取接口
  2. 根据客户端唯一key将生成的验证码保存在redis中
  3. 注册验证,根据key来获取验证码再和用户输入的验证码进行对比校验。

安装redis

这里我是使用的docker进行安装

docker pull redis
docker run --restart=always --log-opt max-size=100m --log-opt max-file=2 -p 16380:6379 --name myredis -v /root/redis/redis.conf:/etc/redis/redis.conf -v /root/redis/data:/data -d redis redis-server /etc/redis/redis.conf  --appendonly yes  --requirepass 151545

上述文件目录请自行创建 最后一个参数是设置密码,保证远程连接的安全性

连接redis

node中使用到了redis这个库

npm install redis -S
const redis = require("redis");
const config = require("./config");

const client = redis.createClient({
  socket: {
    port: config.REDIS_PORT,
    host: config.APP_HOST,
  },
  password: config.REDIS_PASSWORD,
});

// 监听连接事件
client
  .connect()
  .then(() => {
    console.log("redis连接成功");
  })
  .catch((err) => {
    console.log(err || "redis连接出错");
  });

// 操作方法封装 get set
function setString(key, value, expire) {
  return new Promise((resolve, reject) => {
    client
      .set(key, value)
      .then((res) => {
        if (expire) {
          client.expire(key, expire);
        }
        console.log("设置成功");
        resolve(res);
      })
      .catch((err) => {
        console.log("设置失败");
        reject(err);
      });
  });
}
function getString(key) {
  return new Promise((resolve, reject) => {
    if (key) {
      client
        .get(key)
        .then((res) => {
          resolve(res);
        })
        .catch((err) => {
          console.log(`获取${key}失败`);
          reject(err);
        });
    }
  });
}

module.exports = {
  setString,
  getString,
};

验证码获取接口

首先验证码的生成我们选择svg-captcha这个库

代码如下:

const captcha = require("svg-captcha");

function createCaptcha(config = {}) {
  return captcha.create({
    size: 4,
    ignoreChars: "0o1iIl", // 避免生成容易混淆的字符
    noise: 3,
    color: true,
    background: "#f4f4f4",
    fontSize: 60,
    ...config,
  });
}

module.exports = {
  createCaptcha,
};

验证码接口:

const { createCaptcha } = require("../utils/createCaptcha");
const { setString } = require("../app/redis");

class CaptchaController {
  async create(ctx) {
    // 获取用户传递过来的唯一key
    const { sid: captchaKey } = ctx.request.body;
    // 生成验证码
    const code = createCaptcha();
    // 存储在redis中 设置过期事件 过期取出来的值为null
    await setString(captchaKey, code.text, 60 * 3);
    // 设置相应头
    ctx.type = "image/svg+xml";
    ctx.body = code.data;
  }
}

module.exports = new CaptchaController();

路由中引入即可:

const { create } = require("../controller/captcha.controller");

// ...省略部分代码

// 获取验证码
authRouter.post("/captcha", create);

前端展示验证码图片

uuid生成唯一key

npm install uuid -S
import { v4 as uuidv4 } from 'uuid';
const sid = uuidv4();
// 获取图片,这里我是使用转为blob url方式
 const getCathchaImage = async (sid: string) => {
     // 获取验证码接口 这里的sid是一个唯一key 可以使用uuid生成
    const res = await getCaptcha({ sid });
    const blob = new Blob([res], {
      type: 'image/svg+xml',
    });
    const fileURL = URL.createObjectURL(blob);
    // 这里的fileURL就可以设置到img标签上的src属性
     //...
  };
<!--我使用的react-->
<img src={fileURL}/>

验证二维码

这里我是写了个中间件设置再注册接口中。

const { getString } = require("../app/redis");
const { omit } = require("../utils/omit");
const ResponseErrorMessage = require("../constants/responseErrorMessage");

const authCaptcha = async (ctx, next) => {
    //获取传递过来的key和验证码
  const { sid, captcha } = ctx.request.body;
    // 判断是否为空
  if (!sid || !captcha) {
    const error = new Error(ResponseErrorMessage.PARAMETER_ABSENT);
    return ctx.app.emit("error", error, ctx);
  }
  try {
      // 根据唯一key从redis中获取验证码
    const code = await getString(sid);
     // 过期? 
    if (!code) {
      const error = new Error(
        ResponseErrorMessage.VERIFICATION_CODE_HAS_EXPIRED
      );
      return ctx.app.emit("error", error, ctx);
      // 不区分大小写
    } else if (code.toLowerCase() !== captcha.toLowerCase()) {
      const error = new Error(ResponseErrorMessage.VERIFICATION_CODE_ERROR);
      return ctx.app.emit("error", error, ctx);
    } else {
      // 验证通过
      await next();
    }
  } catch (error) {
    console.log(error);
  }
};

module.exports = {
  authCaptcha,
};

参考文献

docker安装

Node实现图形验证码

NodeJS:图片验证码登录

Last modification:August 20, 2022
如果觉得我的文章对你有用,请随意赞赏