A flexible and various captcha package
![Foundation](https://img.shields.io/badge/Golang-Foundation-green.svg)
Base64captcha supports any unicode character and can easily be customized to support Math Chinese Korean Japanese Russian Arabic etc.
1. πππ Doc & Demo
2. πππ Quick start
2.1 π¬π¬π¬ Use history version
Tag v1.2.2
go get github.com/mojocn/base64Captcha@v1.2.2
or edit your go.mod
file to
github.com/mojocn/base64Captcha@v1.2.2
2.2 π₯π₯π₯ Download package
go get -u github.com/mojocn/base64Captcha
For Gopher from mainland China without VPN go get golang.org/x/image
failure solution:
- go version > 1.11
- set env
GOPROXY=https://goproxy.io
2.3 πππ How to code with base64Captcha
2.3.1 πππ Implement Store interface or use build-in memory store
type Store interface {
Set(id string, value string)
Get(id string, clear bool) string
Verify(id, answer string, clear bool) bool
}
2.3.2 πππ Implement Driver interface or use one of build-in drivers
There are some build-in drivers:
- Build-in Driver Digit
- Build-in Driver String
- Build-in Driver Math
- Build-in Driver Chinese
type Driver interface {
DrawCaptcha(content string) (item Item, err error)
GenerateIdQuestionAnswer() (id, q, a string)
}
2.3.3 π΄π΄π΄ βCore code captcha.go
captcha.go
is the entry of base64Captcha which is quite simple.
package base64Captcha
import (
"math/rand"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
type Captcha struct {
Driver Driver
Store Store
}
func NewCaptcha(driver Driver, store Store) *Captcha {
return &Captcha{Driver: driver, Store: store}
}
func (c *Captcha) Generate() (id, b64s string, err error) {
id,content, answer := c.Driver.GenerateIdQuestionAnswer()
item, err := c.Driver.DrawCaptcha(content)
if err != nil {
return "", "", err
}
c.Store.Set(id, answer)
b64s = item.EncodeB64string()
return
}
func (c *Captcha) Verify(id, answer string, clear bool) (match bool) {
match = c.Store.Get(id, clear) == answer
return
}
2.3.4 π΅π΅π΅ βGenerate Base64(image/audio) string
func (c *Captcha) Generate() (id, b64s string, err error) {
id,content, answer := c.Driver.GenerateIdQuestionAnswer()
item, err := c.Driver.DrawCaptcha(content)
if err != nil {
return "", "", err
}
c.Store.Set(id, answer)
b64s = item.EncodeB64string()
return
}
2.3.5 π€Έπ€Έπ€Έ Verify Answer
func (c *Captcha) Verify(id, answer string, clear bool) (match bool) {
match = c.Store.Get(id, clear) == answer
return
}
2.3.6 πππ βFull Example
package main
import (
"encoding/json"
"fmt"
"github.com/mojocn/base64Captcha"
"log"
"net/http"
)
type configJsonBody struct {
Id string
CaptchaType string
VerifyValue string
DriverAudio *base64Captcha.DriverAudio
DriverString *base64Captcha.DriverString
DriverChinese *base64Captcha.DriverChinese
DriverMath *base64Captcha.DriverMath
DriverDigit *base64Captcha.DriverDigit
}
var store = base64Captcha.DefaultMemStore
func generateCaptchaHandler(w http.ResponseWriter, r *http.Request) {
decoder := json.NewDecoder(r.Body)
var param configJsonBody
err := decoder.Decode(¶m)
if err != nil {
log.Println(err)
}
defer r.Body.Close()
var driver base64Captcha.Driver
switch param.CaptchaType {
case "audio":
driver = param.DriverAudio
case "string":
driver = param.DriverString.ConvertFonts()
case "math":
driver = param.DriverMath.ConvertFonts()
case "chinese":
driver = param.DriverChinese.ConvertFonts()
default:
driver = param.DriverDigit
}
c := base64Captcha.NewCaptcha(driver, store)
id, b64s, err := c.Generate()
body := map[string]interface{}{"code": 1, "data": b64s, "captchaId": id, "msg": "success"}
if err != nil {
body = map[string]interface{}{"code": 0, "msg": err.Error()}
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(body)
}
func captchaVerifyHandle(w http.ResponseWriter, r *http.Request) {
decoder := json.NewDecoder(r.Body)
var param configJsonBody
err := decoder.Decode(¶m)
if err != nil {
log.Println(err)
}
defer r.Body.Close()
body := map[string]interface{}{"code": 0, "msg": "failed"}
if store.Verify(param.Id, param.VerifyValue, true) {
body = map[string]interface{}{"code": 1, "msg": "ok"}
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(body)
}
func main() {
http.Handle("/", http.FileServer(http.Dir("./static")))
http.HandleFunc("/api/getCaptcha", generateCaptchaHandler)
http.HandleFunc("/api/verifyCaptcha", captchaVerifyHandle)
fmt.Println("Server is at :8777")
if err := http.ListenAndServe(":8777", nil); err != nil {
log.Fatal(err)
}
}
2.3.7 Example Use Etcd as store
captcha with etcd database as store
3. π¨π¨π¨ Customization
You can customize your captcha display image by implementing interface driver
and interface item.
There are some example for your reference.
- DriverMath
- DriverChinese
- ItemChar
You can even design the captcha struct to whatever you prefer.
4. πππ Thanks
5. πππ Licence
base64Captcha source code is licensed under the Apache Licence, Version 2.0
(http://www.apache.org/licenses/LICENSE-2.0.html).