声明不止,继续 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"
)
@H_403_28@// R type represents an object of Recaptcha and has public property Secret,
@H_403_28@// which is secret obtained from google recaptcha tool admin interface
type R struct {
Secret string
lastError []string
}
@H_403_28@// Struct for parsing json in google's response
type googleResponse struct {
Success bool
ErrorCodes []string `json:"error-codes"`
}
@H_403_28@// url to post submitted re-captcha response to
var postURL = "https://www.google.com/recaptcha/api/siteverify"
@H_403_28@// Verify method,verifies if current request have valid re-captcha response and returns true or false
@H_403_28@// This method also records any errors in validation.
@H_403_28@// 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)
}
@H_403_28@// VerifyResponse is a method similar to `Verify`; but doesn't parse the form for you. Useful if
@H_403_28@// 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
}
@H_403_28@// 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(` <html> <head> <script src='https://www.google.com/recaptcha/api.js'></script> </head> <body> <form action="/submit" method="post"> <div class="g-recaptcha" data-sitekey="%s"></div> <input type="submit"> </form> </body> </html> `,sitekey)
http.HandleFunc("/",func(w http.ResponseWriter,r *http.Request) {
fmt.Fprintf(w,form)
})
http.HandleFunc("/submit",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地址:
@L_301_1@
Star: 619
文档地址:
https://godoc.org/github.com/dchest/captcha
获取:
go get github.com/dchest/captcha
常量
const (
@H_403_28@// Default number of digits in captcha solution.
DefaultLen = 6
@H_403_28@// The number of captchas created that triggers garbage collection used
@H_403_28@// by default store.
CollectNum = 100
@H_403_28@// Expiration time of captchas used by default store.
Expiration = 10 * time.Minute
@H_403_28@// 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.
验证
应用
@H_403_28@// Copyright 2011 Dmitry Chestnykh. All rights reserved.
@H_403_28@// Use of this source code is governed by a MIT-style
@H_403_28@// license that can be found in the LICENSE file.
@H_403_28@// 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,"<br><a href='/'>Try another one</a>")
}
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 = `<!doctype html> <head><title>Captcha Example</title></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> <select id="lang" onchange="changeLang()"> <option value="en">English</option> <option value="ja">Japanese</option> <option value="ru">Russian</option> <option value="zh">Chinese</option> </select> <form action="/process" method=post> <p>Type 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</a> | <a href="#" onclick="playAudio()">Play Audio</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">Download file</a> to play it in the external player. </audio> <input type=hidden name=captchaId value="{{.CaptchaId}}"><br> <input name=captchaSolution> <input type=submit value=Submit> </form> `