Go实战--golang中使用图片和验证码(dchest/captcha)

声明不止,继续 go go go !!!

昨天分享了iris框架中,如何使用Google的recaptcha。今天就一起分享学一学golang中如何使用图片验证码以及语音验证码,当然最开始我们还是要面向github编程了。

使用recaptcha

其实recaptcha的使用很简单,这里不使用iris框架,也很容易自己实现的。

https://github.com/haisum/recaptcha/blob/master/recaptcha.go

package recaptcha

import (
    "encoding/json"
    "io/ioutil"
    "net/http"
    "net/url"
    "time"
)

// R type represents an object of Recaptcha and has public property Secret,
// which is secret obtained from google recaptcha tool admin interface
type R struct {
    Secret    string
    lastError []string
}

// Struct for parsing json in google's response
type googleResponse struct {
    Success    bool
    ErrorCodes []string `json:"error-codes"`
}

// url to post submitted re-captcha response to
var postURL = "https://www.google.com/recaptcha/api/siteverify"

// Verify method, verifies if current request have valid re-captcha response and returns true or false
// This method also records any errors in validation.
// These errors can be received by calling LastError() method.
func (r *R) Verify(req http.Request) bool {
    response := req.FormValue("g-recaptcha-response")
    return r.VerifyResponse(response)
}

// VerifyResponse is a method similar to `Verify`; but doesn't parse the form for you.  Useful if
// you're receiving the data as a JSON object from a javascript app or similar.
func (r *R) VerifyResponse(response string) bool {
    r.lastError = make([]string, 1)
    client := &http.Client{Timeout: 20 * time.Second}
    resp, err := client.PostForm(postURL,
        url.Values{"secret": {r.Secret}, "response": {response}})
    if err != nil {
        r.lastError = append(r.lastError, err.Error())
        return false
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        r.lastError = append(r.lastError, err.Error())
        return false
    }
    gr := new(googleResponse)
    err = json.Unmarshal(body, gr)
    if err != nil {
        r.lastError = append(r.lastError, err.Error())
        return false
    }
    if !gr.Success {
        r.lastError = append(r.lastError, gr.ErrorCodes...)
    }
    return gr.Success
}

// LastError returns errors occurred in last re-captcha validation attempt
func (r R) LastError() []string {
    return r.lastError
}

使用:

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/haisum/recaptcha"
)

func main() {
    sitekey := "6LfiVjcUAAAAAJyjCEGVyTpmFqlpOMGVIZpZPy6p"
    re := recaptcha.R{
        Secret: "6LfiVjcUAAAAAJ7wALWYNew2yx0qbT0WxRR-kYu9",
    }

    form := fmt.Sprintf(`
        
            
                
            
            
                
`
, sitekey) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, form) }) http.HandleFunc("/submit", func(w http.ResponseWriter, r *http.Request) { isValid := re.Verify(*r) if isValid { fmt.Fprintf(w, "Valid") } else { fmt.Fprintf(w, "Invalid! These errors ocurred: %v", re.LastError()) } }) log.Printf("\n Starting server on http://localhost:8080 .") err := http.ListenAndServe(":8080", nil) if err != nil { log.Fatalf("Could not start server. %s", err) } }

dchest/captcha

上面是小试牛刀,现在开始一起了解dchest/captcha。

github地址:
https://github.com/dchest/captcha

Star: 619

文档地址:
https://godoc.org/github.com/dchest/captcha

获取:
go get github.com/dchest/captcha

常量

const (
    // Default number of digits in captcha solution.
    DefaultLen = 6
    // The number of captchas created that triggers garbage collection used
    // by default store.
    CollectNum = 100
    // Expiration time of captchas used by default store.
    Expiration = 10 * time.Minute

    // Standard width and height of a captcha image.
    StdWidth  = 240
    StdHeight = 80
)

默认是六位的验证码
当达到100个验证码的时候,会进行垃圾回收
验证码十分钟过期
图片验证码尺寸240*80

func New

func New() string

New creates a new captcha with the standard length, saves it in the internal storage and returns its id.
创建一个6位的验证码,存入内存,并返回id
func NewLen

func NewLen(length int) (id string)

NewLen is just like New, but accepts length of a captcha solution as the argument.
跟new的作用一样,就是多了一个参数,可以自定义验证码的位数。

func RandomDigits

func RandomDigits(length int) []byte

RandomDigits returns a byte slice of the given length containing pseudorandom numbers in range 0-9. The slice can be used as a captcha solution.
生成随机数,返回切片,长度为length

func Reload

func Reload(id string) bool

Reload generates and remembers new digits for the given captcha id. This function returns false if there is no captcha with the given id.
刷新,也就是重新载入,但是验证码id是不变的。

func Server

func Server(imgWidth, imgHeight int) http.Handler

Server returns a handler that serves HTTP requests with image or audio representations of captchas. Image dimensions are accepted as arguments. The server decides which captcha to serve based on the last URL path component: file name part must contain a captcha id, file extension — its format (PNG or WAV).

func SetCustomStore

func SetCustomStore(s Store)

SetCustomStore sets custom storage for captchas, replacing the default memory store. This function must be called before generating any captchas.
设置本地存储验证码而不是内存。

func Verify

func Verify(id string, digits []byte) bool

Verify returns true if the given digits are the ones that were used to create the given captcha id.

The function deletes the captcha with the given id from the internal storage, so that the same captcha can’t be verified anymore.
验证

func VerifyString

func VerifyString(id string, digits string) bool

VerifyString is like Verify, but accepts a string of digits. It removes spaces and commas from the string, but any other characters, apart from digits and listed above, will cause the function to return false.
验证

应用

// Copyright 2011 Dmitry Chestnykh. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

// example of HTTP server that uses the captcha package.
package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "text/template"

    "github.com/dchest/captcha"
)

var formTemplate = template.Must(template.New("example").Parse(formTemplateSrc))

func showFormHandler(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path != "/" {
        http.NotFound(w, r)
        return
    }
    d := struct {
        CaptchaId string
    }{
        captcha.NewLen(4),
    }
    if err := formTemplate.Execute(w, &d); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

func processFormHandler(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 solution! No robots allowed!\n")
    } else {
        io.WriteString(w, "Great job, human! You solved the captcha.\n")
    }
    io.WriteString(w, "
Try another one"
) } func main() { http.HandleFunc("/", showFormHandler) http.HandleFunc("/process", processFormHandler) http.Handle("/captcha/", captcha.Server(captcha.StdWidth, captcha.StdHeight)) fmt.Println("Server is at localhost:8080") if err := http.ListenAndServe("localhost:8080", nil); err != nil { log.Fatal(err) } } const formTemplateSrc = ` Captcha Example

Type the numbers you see in the picture below:

Captcha image

Reload | Play Audio
`

Go实战--golang中使用图片和验证码(dchest/captcha)_第1张图片

Go实战--golang中使用图片和验证码(dchest/captcha)_第2张图片

你可能感兴趣的:(go,Go从不放弃到实战)