[TOC]
Let’s use GO to play with the verification code
Hi, I’m the little magic boy Nezha, defer
in GO we shared last time, let’s review it again
- Shared what defer is
- A simple illustration of the stack and queue
- Defer's data structure and implementation principle, specific source code display
- 3 rules of
defer
in GO
If the GO for the defer
realization of the principle a little bit interested, you are welcome to view the article realization of the principle in GO defer the
Today we will share some GO
, let’s grow while playing
Introduction to GO verification code
The verification codes we usually use are roughly divided into these types, let's sort them out:
- Traditional input form
Enter the numbers, text, letters, etc. on the picture
- Enter the type of graphic verification code
This is mainly for advertising
- Pure behavior verification code
For example, swipe as prompted, etc.
- Icon selection and behavior-assisted verification code
For example, when we buy a train ticket, the verification code, various icons let you choose
- Click-type graphic verification and behavior assistance
For example, the verification code of a treasure
- Smart verification code
For example, tap the smart verification code
GO verification code case
Let’s play with the first one today, the one that uses the most verification code.
Will use this verification code library of GO to complete, github.com/dchest/captcha
If we C/C++
like 060d7e2b281bb0, we encapsulate a lot of the underlying processing to achieve it, it is quite tiring, GO is really good, there are many packages used, we can use it, we can also stand On the shoulders of giants, learn the implementation methods in the source code, and learn the design ideas of the big guys.
Install captcha
library
You can download it and use it with the following command
go get github.com/dchest/captcha
When we use the captcha
GOLAND
, we can look at the source directory
Source directory
- Specific use cases with source code
- Specific sample pictures
- Realization of related audio processing
- Implementation of verification code processing
- Realization of image processing
- Realization of random number processing
- and many more...
Supported languages
The audio currently supported by this library has 4 languages:
- English
- Chinese
- Russian
- Japanese
Verification code default parameters
The default size of the verification code in the library is width 240 px, height 80 px
image.go in the source code
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
}
The characters contained in the random number
The following are the characters allowed in the verification code id, which can be seen in the source code
random.go
in the source package
// idChars are characters allowed in captcha id.
var idChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
About audio processing
sounds.go
file in the source code
Currently only supports 4 languages "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.longestDigitSndLen()*len(digits) + intdur)
// Create buffer and write audio to it.
sil := makeSilence(sampleRate / 5)
bufcap := 3*len(beepSound) + 2*len(sil) + len(bg) + len(endingBeepSound)
a.body = bytes.NewBuffer(make([]byte, 0, bufcap))
// Write prelude, three beeps.
a.body.Write(beepSound)
a.body.Write(sil)
a.body.Write(beepSound)
a.body.Write(sil)
a.body.Write(beepSound)
// Write digits.
pos := intervals[0]
for i, v := range numsnd {
mixSound(bg[pos:], v)
pos += len(v) + intervals[i+1]
}
a.body.Write(bg)
// Write ending (one beep).
a.body.Write(endingBeepSound)
return a
}
The data about language is in the digitSounds
map
Seeing this, it’s a bit like doing font parsing and data parsing in embedded
var digitSounds = map[string][][]byte{
"en": [][]byte{
{ // 0
0x80, 0x7f, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x80,
...
},
"ru": [][]byte{
{ // 0
0x7f, 0x7f, 0x7e, 0x7f, 0x7f, 0x7e, 0x7f, 0x7e, 0x7f, 0x7f, 0x7e,
...
},
"zh": [][]byte{
{ // 0
0x7f, 0x80, 0x7f, 0x80, 0x80, 0x7f, 0x80, 0x7f, 0x80, 0x7f, 0x80,
...
},
"ja": [][]byte{
{ // 0
0x7f, 0x80, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x83,
...
},
Start the demonstration of the case
my_captcha.html implemented as follows
For the time being about the language of audio, I wrote 2 2 languages
- English
- Chinese
<!doctype html>
<head>
<title>GO 简单制作验证码案例</title>
<style>
input{
margin-top: 30px;
}
</style>
</head>
<body>
<script>
// 设置语言
function setSrcQuery(e, q) {
var src = e.src;
var p = src.indexOf('?');
if (p >= 0) {
src = src.substr(0, p);
}
e.src = src + "?" + q
}
// 播放音频
function playAudio() {
var le = document.getElementById("lang");
var lang = le.options[le.selectedIndex].value;
var e = document.getElementById('audio')
setSrcQuery(e, "lang=" + lang)
e.style.display = 'block';
e.autoplay = 'true';
return false;
}
// 切换语言
function changeLang() {
var e = document.getElementById('audio')
if (e.style.display == 'block') {
playAudio();
}
}
// 重新加载
function reload() {
setSrcQuery(document.getElementById('image'), "reload=" + (new Date()).getTime());
setSrcQuery(document.getElementById('audio'), (new Date()).getTime());
return false;
}
</script>
<div align="center" >
<select id="lang" onchange="changeLang()">
<option value="en">英文</option>
<option value="zh">中文</option>
</select>
</div>
<form action="/processCapcha" method=post align="center">
<p>请输入你在下面的图片中看到的数字:</p>
<p><img id=image src="/captcha/{{.CaptchaId}}.png" alt="Captcha image"></p>
<a href="#" onclick="reload()">重新加载</a> | <a href="#" onclick="playAudio()">播放音频验证码</a>
<audio id=audio controls style="display:none" src="/captcha/{{.CaptchaId}}.wav" preload=none>
You browser doesn't support audio.
<a href="/captcha/download/{{.CaptchaId}}.wav">下载文件</a> to play it in the external player.
</audio>
<input type=hidden name=captchaId value="{{.CaptchaId}}" align=center><br>
<input name=captchaSolution align=center>
<input type=submit value=Submit>
</form>
main.go
- Show verification code
- Process the verification code and display the result
- Reload verification code
- Play verification code audio
package main
import (
"github.com/dchest/captcha"
"io"
"io/ioutil"
"log"
"net/http"
"text/template"
)
const filePath = "./my_captcha.html"
// 读取 html 文件
func readHtml() string {
var bytes []byte
var err error
if bytes, err = ioutil.ReadFile(filePath); err != nil {
log.Fatalf("ioutil.ReadFile error filePath = %s , err :"+filePath, err)
return ""
}
return string(bytes)
}
// 读取html 文件,转成template.Template 指针
var formTemplate = template.Must(template.New("myCaptcha").Parse(readHtml()))
// 显示验证码
func showCaptcha(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
d := struct {
CaptchaId string
}{
captcha.New(),
}
// Execute将解析后的模板应用到指定的数据对象,并将输出写入wr
if err := formTemplate.Execute(w, &d); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
// 处理验证码,跳转结果页面
func resultPage(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if !captcha.VerifyString(r.FormValue("captchaId"), r.FormValue("captchaSolution")) {
io.WriteString(w, "错误的验证码,请重新输入\n")
} else {
io.WriteString(w, "验证吗正确,你很棒哦!!\n")
}
io.WriteString(w, "<br><a href='/'>再试一下</a>")
}
func main() {
// 简单设置log参数
log.SetFlags(log.Lshortfile | log.LstdFlags)
http.HandleFunc("/", showCaptcha)
http.HandleFunc("/processCapcha", resultPage)
http.Handle("/captcha/", captcha.Server(captcha.StdWidth, captcha.StdHeight))
log.Println("starting server : 8888")
if err := http.ListenAndServe("localhost:8888", nil); err != nil {
log.Fatal(err)
}
}
The width and height of the above code is like this
StdWidth = 240
StdHeight = 80
The HandleFunc
looks like this. I shared it when I introduced gin before. You can look back at the article and let us explore the net/http code flow
// HandleFunc registers the handler function for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
Actual effect of verification code
click to play the audio verification code, you can see this effect
The audio will play different voices according to the language we choose, and read the numbers on the picture
to sum up
- Sorting out the types of verification codes
- Installation of verification code library
- Source code introduction of verification code library
- Practice, coding
- Verification code performance display
Welcome to like, follow, favorite
Friends, your support and encouragement are my motivation to keep sharing and improve quality
Okay, that's it for this time, How to use GOLANG to send mail next time
Technology is open, and our mindset should be more open. Embrace the change, live toward the sun, and work hard to move forward.
I am little magic boy , welcome to like and follow the collection, see you next time~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。