文章目录
我们用GO玩一下验证码
嗨,我是小魔童哪吒,咱们上次分享的GO 中 defer
的实现原理,再来回顾一下吧
- 分享了defer是什么
- 简单示意了栈和队列
- defer的数据结构和实现原理,具体的源码展示
- GO 中
defer
的 3 条规则
要是对 GO 中 defer
实现原理还有点兴趣的话,欢迎查看文章 GO 中 defer的实现原理
今天我们来分享一些使用 GO
实现小案例,咱们边玩边成长
GO 的验证码介绍
我们平时使用到的验证码大致分为这几种,咱们梳理一下:
- 传统输入的形式
输入图片上的数字,文字,字母等等
- 输入类型的图形验证码
这个主要是来打广告的
- 纯行为验证码
例如,按照提示滑动等等
- 图标选择与行为辅助的验证码
例如咱们买火车票的时候验证码,各种图标让你选
- 点击式的图文验证与行为辅助
例如某宝的验证码
- 智能验证码
例如,点触智能验证码
GO 验证码案例
我们今天就来玩一玩第一种,使用最多的一种验证码吧
会使用 GO 的这个验证码库来完成,github.com/dchest/captcha
若我们向C/C++
一样,将很多的底层处理都是我们自己来封装来实现的话,那还是挺累人的,GO 这一点确实蛮好,有很多使用的包,咱们在使用之余,也可以站在巨人的肩膀人,学习源码中的实现方式,学习大佬们的设计思想。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lC6WxucK-1625666538870)(https://i.loli.net/2021/06/19/q1joYsKZCSmT7Ep.gif)]
安装captcha
库
大家使用如下命令就可以下载下来使用
go get github.com/dchest/captcha
当我们在GOLAND
中用到 captcha
库的时候,咱们可以看看源码目录
源码目录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lAmTlVq9-1625666538873)(https://i.loli.net/2021/06/18/na2EQkyJZtxi1Pw.png)]
- 有源码的具体使用案例
- 具体的示例图片
- 相关音频处理的实现
- 验证码处理的实现
- 图片处理的实现
- 随机数处理的实现方式
- 等等…
支持的语言
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jiT2gDwt-1625666538877)(https://i.loli.net/2021/06/18/3svjDucamYOJp8n.png)]
这个库目前支持的音频有 4 种语言:
- 英文
- 中文
- 俄文
- 日文
验证码默认参数
库中验证码的大小默认是 宽 240 px,高 80 px
在源码中的 image.go
const (
// Standard width and height of a captcha image.
StdWidth = 240
StdHeight = 80
// Maximum absolute skew factor of a single digit.
maxSkew = 0.7
// Number of background circles.
circleCount = 20
)
type Image struct {
*image.Paletted
numWidth int
numHeight int
dotSize int
rng siprng
}
随机数包含的字符
如下是验证码id中允许的字符 ,可以在源码中看到
源码包中的 random.go
// idChars are characters allowed in captcha id.
var idChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
关于音频的处理
在源码的 sounds.go
文件
目前对于音频只支持 4 种语言,"en", "ja", "ru", "zh".
/ NewAudio returns a new audio captcha with the given digits, where each digit
// must be in range 0-9. Digits are pronounced in the given language. If there
// are no sounds for the given language, English is used.
//
// Possible values for lang are "en", "ja", "ru", "zh".
func NewAudio(id string, digits []byte, lang string) *Audio {
a := new(Audio)
// Initialize PRNG.
a.rng.Seed(deriveSeed(audioSeedPurpose, id, digits))
if sounds, ok := digitSounds[lang]; ok {
a.digitSounds = sounds
} else {
a.digitSounds = digitSounds["en"]
}
numsnd := make([][]byte, len(digits))
nsdur := 0
for i, n := range digits {
snd := a.randomizedDigitSound(n)
nsdur += len(snd)
numsnd[i] = snd
}
// Random intervals between digits (including beginning).
intervals := make([]int, len(digits)+1)
intdur := 0
for i := range intervals {
dur := a.rng.Int(sampleRate, sampleRate*3) // 1 to 3 seconds
intdur += dur
intervals[i] = dur
}
// Generate background sound.
bg := a.makeBackgroundSound(a.longestDigitSndL