This is the 21st day of my participation in Gwen Challenge

Let’s play with captcha with GO

Hi, I’m Nezha. Let’s review the implementation principle of Defer in GO we shared last time

  • What is deferred after sharing it
  • The stack and queue are briefly illustrated
  • Defer’s data structure and implementation principle, as well as the specific source code
  • GO in thedeferthe3rule

If you’re interested in the implementation of defer in GO, please check out the implementation of defer in the GO article

Today we are going to share some small implementation cases using GO, and let’s play and grow as we GO

GO verification code introduction

We usually use the verification code is roughly divided into these kinds, let’s comb through:

  • Traditional input

Enter numbers, words, letters, etc on the picture

  • Graphic verification code for input type

This is mainly for advertising

  • Pure behavior verification code

For example, follow the prompts to slide, etc

  • Icon selection with behavior assisted captcha

For example, when we buy train tickets, verification code, various ICONS for you to choose

  • Click – on – text verification and behavior assistance

For example, the verification code of a treasure

  • Intelligent verification code

For example, tap smart captcha

GO verification code case

Let’s play with the first one, the most used captcha

Will use the GO this verification code library to accomplish, github.com/dchest/captcha

If we like C/C++, will be a lot of the bottom processing is our own package to achieve, it is still very tiring, GO this point is really good, there are a lot of packages, we use, can also stand on the shoulders of giants, learning the source code of the implementation, learning the design ideas of the big guys.

The installationcaptchalibrary

You can use the following command to download down to use

go get github.com/dchest/captcha
Copy the code

When we use the CaptCHA library in GOLAND, we can look at the source directory

Source directory

  • There are specific use cases for the source code
  • Concrete example pictures
  • Implementation of related audio processing
  • Verification code processing implementation
  • Image processing implementation
  • Random number processing implementation
  • And so on…

Supported languages

The library currently supports audio in four languages:

  • English
  • Chinese
  • ru
  • Japanese

Verification code Default parameter

The default size of the verification code in the library is 240 px wide and 80 px high

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
}
Copy the code

The character contained in the random number

The following characters are allowed in the captcha 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")
Copy the code

About audio processing

In the source file of sounds.go

Currently only 4 languages are supported for audio: “en”, “JA “, “ru”, and “en”.

/ 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
}
Copy the code

The data about language is in digitSounds Map

See this, a bit like doing font parsing and embedded inside the data parsing

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. },Copy the code

Start the case presentation

My_captcha.html is implemented as follows

For the time being, there are two languages for audio

  • English
  • Chinese
<! doctypehtml>
<head>
    <title>GO simple verification code case</title>
    <style>
        input{
            margin-top: 30px;
        }
    </style>
</head>
<body>
<script>

    // Set the language
    function setSrcQuery(e, q) {
        var src = e.src;
        var p = src.indexOf('? ');
        if (p >= 0) {
            src = src.substr(0, p);
        }
        e.src = src + "?" + q
    }

    // Play the audio
    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;
    }

    // Switch languages
    function changeLang() {
        var e = document.getElementById('audio')
        if (e.style.display == 'block') { playAudio(); }}// Reload
    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">English</option>
        <option value="zh">Chinese</option>
    </select>
</div>

<form action="/processCapcha" method=post align="center">
    <p>Please enter the numbers you see in the picture below:</p>
    <p><img id=image src="/captcha/{{.CaptchaId}}.png" alt="Captcha image"></p>
    <a href="#" onclick="reload()">Reload the</a>   |   <a href="#" onclick="playAudio()">Play the audio verification code</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">The download file</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>
Copy the code

main.go

  • Display verification code
  • Process captcha and display results
  • Overloaded captcha
  • Play the audio of the verification code
package main

import (
	"github.com/dchest/captcha"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"text/template"
)

const filePath = "./my_captcha.html"
// Read the HTML file
func readHtml(a) string {
	var bytes []byte
	var err error
	ifbytes, err = ioutil.ReadFile(filePath); err ! =nil {
		log.Fatalf("ioutil.ReadFile error filePath = %s , err :"+filePath, err)
		return ""
	}

	return string(bytes)
}

// Read the HTML file and turn it into a template. template pointer
var formTemplate = template.Must(template.New("myCaptcha").Parse(readHtml()))

// Display the verification code
func showCaptcha(w http.ResponseWriter, r *http.Request) {
	ifr.URL.Path ! ="/" {
		http.NotFound(w, r)
		return
	}
	d := struct {
		CaptchaId string
	}{
		captcha.New(),
	}
	// Execute applies the parsed template to the specified data object and writes the output to wR
	iferr := formTemplate.Execute(w, &d); err ! =nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

// Process the verification code, jump to the result page
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, "Wrong captcha, please retype \n")}else {
		io.WriteString(w, "Verification? Correct, you are great!! \n")
	}
	io.WriteString(w, "

)}func main(a) { // Simply set the log parameter 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) } } Copy the code

The width and height of the code above looks like this

StdWidth  = 240
StdHeight = 80
Copy the code

The above HandleFunc callback function looks like this, which was shared earlier in the introduction of GIN, and can be taken back to the article to 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)
	}
Copy the code

Verification code actual effect

This is what happens when you click on the Play audio captcha

The audio, depending on the language we choose, plays different sounds and reads the numbers on the pictures

conclusion

  • Verification code type sorting
  • Installation of the verification code library
  • Verification code library source code introduction
  • Practical operation, coding
  • Verification code effect display

Welcome to like, follow and favorites

Friends, your support and encouragement, I insist on sharing, improve the quality of the power

Ok, that’s it for now. How do I send emails using GOLANG next time

Technology is open, our mentality, should be more open. Embrace change, live in the sun, and strive to move forward.

I am Nezha, welcome to like, see you next time ~