使用captcha库实现人机验证的图片验证

安装captcha库

使用go get命令获取captcha库

go get github.com/dchest/captcha

构建响应函数

// 发送图片验证码图片(gee7为自搭建web框架,可使用gin框架代替)
func Picverfi(db *sql.DB) gee7.HandlerFunc {
 return func(ctx *gee7.Context) {

  // 生成验证码
  id := uuid.New().String() //生成唯一标识符
  code := captcha.RandomDigits(4)
  img := captcha.NewImage(id, code, captcha.StdWidth, captcha.StdHeight)
 
  var buf bytes.Buffer
  _, err := img.WriteTo(&buf)
  if err != nil {
   ctx.Returnfunc(401"出错了,点击重试"nil)
  }

  // 转化为base64
  encodedImage := base64.StdEncoding.EncodeToString(buf.Bytes())
    // 将验证码和图片id存储到数据库中
  verificationCode := VerificationCode{PicCode: code, CreatedAt: time.Now().Unix()}
  _, err = db.Exec("INSERT INTO verification_codes (id, code, created_at) VALUES (?, ?, ?)", id, verificationCode.PicCode, verificationCode.CreatedAt)
  if err != nil {
   ctx.Returnfunc(http.StatusInternalServerError, "Internal Server Error:"+err.Error(), nil)
   return
  }

  // 返回图片与唯一标识符
  ctx.Returnfunc(200"ok", gee7.H{
   "picid": id,
   "png":   encodedImage,
  })

  fmt.Printf("id=%#v\ncode=%d", id, code)
 }
}

gee7为自搭建web框架,可使用gin框架代替

需要了解gee7框架的内容可以访问:

自搭建go web框架

下面对逻辑进行解析
  1. 最核心的的内容是图片验证码的生成与响应
// 生成验证码图片
img := captcha.NewImage(id, code, captcha.StdWidth, captcha.StdHeight)//其中id为标识符,code为验证码
//读取验证码图片
  var buf bytes.Buffer
  _, err := img.WriteTo(&buf)
  if err != nil {
   ctx.Returnfunc(401, "出错了,点击重试", nil)
  }

  // 将验证码图片转化为base64格式
  encodedImage := base64.StdEncoding.EncodeToString(buf.Bytes())

这时输出encodedImage给前端,前端进行解码就可以看到验证码图片了,

验证码图片的问题解决了,接下来就是验证的逻辑

  1. 验证逻辑

将验证码存入数据库,当用户验证的时候在数据库中查找是否有这一条验证码

但是还需要确定用户上传的验证码是服务器发送的图片中的验证码,所以就需要对验证码进行标识,在用户提交验证的时候通过表示查找验证码,这样就确保验证码的唯一对应性

我们这里使用uuid库生成唯一标识符,这种标识符不重复,避免数据冲突的错误

id := uuid.New().String() //生成唯一标识符

再加上一个验证码过期时间的条件,就完成了基本的验证逻辑

如果需要减少空间浪费,可以在通过验证之后顺手增加一条删除验证码信息的代码,在通过验证之后删除MySQL中对应的数据,减少空间浪费.

验证逻辑:

// 图片验证码验证操作:用户传入图片id(唯一标识符发送图片信息时给的),+验证码
func Verifypiccode(db *sql.DB, id string, code []byte) error {
 var createdAt int64
 err := db.QueryRow("SELECT created_at FROM verification_codes WHERE id = ? AND code = ?", id, code).Scan(&createdAt)
 if err != nil {
  return err
 }
 // 删除验证码
 db.Exec("DELETE FROM verification_codes WHERE id = ?", id)
 if time.Now().Unix() > createdAt+5*60 { //时效5分钟
  return fmt.Errorf("验证码过期")
 }
 return nil
}

前端vue3组件

<template>
  <div>
    <button @click="getVerificationImage">获取验证码图片</button>
    <div v-if="verificationImage">
      <img :src="decodeBase64(verificationImage.png)" alt="验证码图片">
    </div>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      verificationImagenull,
      picid''
    };
  },
  methods: {
    async getVerificationImage() {
    try {
      const response = await axios.get('http://localhost:8888/verifypic');
      if (response.data.code === 200) {
        this.verificationImage = response.data.data;
        this.picid = response.data.data.picid;
        // 触发自定义事件,将 picid 传递给父组件
        this.$emit('verificationImage'this.picid);
      } else {
        console.error(response.data.msg);
      }
    } catch (error) {
      console.error('获取验证码图片失败', error);
    }
  },
    decodeBase64(base64Data) {
      return `data:image/png;base64, ${base64Data}`;
    }
  }
};
</script>

本文由 mdnice 多平台发布

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值