• golang 之验证码api


     

    知识一:如何返回一个json数据?

        先定义一个结构体ResponseData,2个参数,并返回的是json数据,key就是json后定义的名称

        type ResponseData struct {

           Status  bool         `json:"status"`

           Message string    `json:"message"`

        }

        再定义一个函数,返回结构体的指针。【也就是初始化了一个类,把对象返回一个对象。】

        func NewJsondata() *ResponseData {

           return &ResponseData{}

        }

        使用方法

        result := NewJsondata() // 初始化,返回指针

        result.Status = true  // 赋值,和类赋值相同

        result.Message = "验证成功"

    知识二:如何定义一个全局变量?

        在函数外定义的都是全局变量

        var RegisterCode  map[string] int64 = make(map[string] int64)

    知识三:如何获取当前时间戳?

        t := time.Now()

        td := t.Unix()

    知识四:map的操作 增加、循环、删除?

        RegisterCode["name"] =“HaiRui”  //增加值

        for k :=range RegisterCode{ //循环

             oldtt := RegisterCode[k] //根据key获取值

             if td - oldtt > 300  { //条件判断

             delete(RegisterCode,k); // 删除值

             }

         }

    全部代码【海瑞博客】:

    package main
    
    import (
    	crand "crypto/rand"
    	"fmt"
    	"image"
    	"image/color"
    	"image/png"
    	"io"
    	"math/rand"
    	"net/http"
    	"strconv"
    	"time"
    	"encoding/json"
    )
    
    const (
    	stdWidth  = 100
    	stdHeight = 40
    	maxSkew   = 2
    )
    
    const (
    	fontWidth  = 5
    	fontHeight = 8
    	blackChar  = 1
    )
    
    type Validate_Data struct {
    	code string
    	tt int64
    }
    
    type ResponseData struct {
    	Status     bool     `json:"status"`
    	Message string      `json:"message"`
    }
    
    func NewJsondata() *ResponseData {
    	return &ResponseData{}
    }
    
    
    var RegisterCode  map[string] int64 = make(map[string] int64)
    
    
    var font = [][]byte{
    	{ // 0
    		0, 1, 1, 1, 0,
    		1, 0, 0, 0, 1,
    		1, 0, 0, 0, 1,
    		1, 0, 0, 0, 1,
    		1, 0, 0, 0, 1,
    		1, 0, 0, 0, 1,
    		1, 0, 0, 0, 1,
    		0, 1, 1, 1, 0},
    	{ // 1
    		0, 0, 1, 0, 0,
    		0, 1, 1, 0, 0,
    		1, 0, 1, 0, 0,
    		0, 0, 1, 0, 0,
    		0, 0, 1, 0, 0,
    		0, 0, 1, 0, 0,
    		0, 0, 1, 0, 0,
    		1, 1, 1, 1, 1},
    	{ // 2
    		0, 1, 1, 1, 0,
    		1, 0, 0, 0, 1,
    		0, 0, 0, 0, 1,
    		0, 0, 0, 1, 1,
    		0, 1, 1, 0, 0,
    		1, 0, 0, 0, 0,
    		1, 0, 0, 0, 0,
    		1, 1, 1, 1, 1},
    	{ // 3
    		1, 1, 1, 1, 0,
    		0, 0, 0, 0, 1,
    		0, 0, 0, 1, 0,
    		0, 1, 1, 1, 0,
    		0, 0, 0, 1, 0,
    		0, 0, 0, 0, 1,
    		0, 0, 0, 0, 1,
    		1, 1, 1, 1, 0},
    	{ // 4
    		1, 0, 0, 1, 0,
    		1, 0, 0, 1, 0,
    		1, 0, 0, 1, 0,
    		1, 0, 0, 1, 0,
    		1, 1, 1, 1, 1,
    		0, 0, 0, 1, 0,
    		0, 0, 0, 1, 0,
    		0, 0, 0, 1, 0},
    	{ // 5
    		1, 1, 1, 1, 1,
    		1, 0, 0, 0, 0,
    		1, 0, 0, 0, 0,
    		1, 1, 1, 1, 0,
    		0, 0, 0, 0, 1,
    		0, 0, 0, 0, 1,
    		0, 0, 0, 0, 1,
    		1, 1, 1, 1, 0},
    	{ // 6
    		0, 0, 1, 1, 1,
    		0, 1, 0, 0, 0,
    		1, 0, 0, 0, 0,
    		1, 1, 1, 1, 0,
    		1, 0, 0, 0, 1,
    		1, 0, 0, 0, 1,
    		1, 0, 0, 0, 1,
    		0, 1, 1, 1, 0},
    	{ // 7
    		1, 1, 1, 1, 1,
    		0, 0, 0, 0, 1,
    		0, 0, 0, 0, 1,
    		0, 0, 0, 1, 0,
    		0, 0, 1, 0, 0,
    		0, 1, 0, 0, 0,
    		0, 1, 0, 0, 0,
    		0, 1, 0, 0, 0},
    	{ // 8
    		0, 1, 1, 1, 0,
    		1, 0, 0, 0, 1,
    		1, 0, 0, 0, 1,
    		0, 1, 1, 1, 0,
    		1, 0, 0, 0, 1,
    		1, 0, 0, 0, 1,
    		1, 0, 0, 0, 1,
    		0, 1, 1, 1, 0},
    	{ // 9
    		0, 1, 1, 1, 0,
    		1, 0, 0, 0, 1,
    		1, 0, 0, 0, 1,
    		1, 1, 0, 0, 1,
    		0, 1, 1, 1, 1,
    		0, 0, 0, 0, 1,
    		0, 0, 0, 0, 1,
    		1, 1, 1, 1, 0},
    }
    
    type Image struct {
    	*image.NRGBA
    	color   *color.NRGBA
    	width   int //a digit width
    	height  int //a digit height
    	dotsize int
    }
    
    func init() {
    	rand.Seed(int64(time.Second))
    
    }
    
    func NewImage(digits []byte, width, height int) *Image {
    	img := new(Image)
    	r := image.Rect(img.width, img.height, stdWidth, stdHeight)
    	img.NRGBA = image.NewNRGBA(r)
    	img.color = &color.NRGBA{
    		uint8(rand.Intn(129)),
    		uint8(rand.Intn(129)),
    		uint8(rand.Intn(129)),
    		0xFF}
    	// Draw background (10 random circles of random brightness)
    	img.calculateSizes(width, height, len(digits))
    	img.fillWithCircles(10, img.dotsize)
    	maxx := width - (img.width+img.dotsize)*len(digits) - img.dotsize
    	maxy := height - img.height - img.dotsize*2
    	x := rnd(img.dotsize*2, maxx)
    	y := rnd(img.dotsize*2, maxy)
    	// Draw digits.
    	for _, n := range digits {
    		img.drawDigit(font[n], x, y)
    		x += img.width + img.dotsize
    	}
    	// Draw strike-through line.
    	img.strikeThrough()
    	return img
    
    }
    
    func (img *Image) WriteTo(w io.Writer) (int64, error) {
    	return 0, png.Encode(w, img)
    
    }
    
    func (img *Image) calculateSizes(width, height, ncount int) {
    	// Goal: fit all digits inside the image.
    	var border int
    	if width > height {
    		border = height / 5
    	} else {
    		border = width / 5
    	}
    	// Convert everything to floats for calculations.
    	w := float64(width - border*2)  //268
    	h := float64(height - border*2) //48
    	// fw takes into account 1-dot spacing between digits.
    	fw := float64(fontWidth) + 1 //6
    	fh := float64(fontHeight)    //8
    	nc := float64(ncount)        //7
    	// Calculate the width of a single digit taking into account only the
    	// width of the image.
    	nw := w / nc //38
    	// Calculate the height of a digit from this width.
    	nh := nw * fh / fw //51
    	// Digit too high?
    	if nh > h {
    		// Fit digits based on height.
    		nh = h //nh = 44
    		nw = fw / fh * nh
    	}
    	// Calculate dot size.
    	img.dotsize = int(nh / fh)
    	// Save everything, making the actual width smaller by 1 dot to account
    	// for spacing between digits.
    	img.width = int(nw)
    	img.height = int(nh) - img.dotsize
    
    }
    
    func (img *Image) fillWithCircles(n, maxradius int) {
    	color := img.color
    	maxx := img.Bounds().Max.X
    	maxy := img.Bounds().Max.Y
    	for i := 0; i < n; i++ {
    		setRandomBrightness(color, 255)
    		r := rnd(1, maxradius)
    		img.drawCircle(color, rnd(r, maxx-r), rnd(r, maxy-r), r)
    	}
    
    }
    
    func (img *Image) drawHorizLine(color color.Color, fromX, toX, y int) {
    	for x := fromX; x <= toX; x++ {
    		img.Set(x, y, color)
    	}
    
    }
    
    func (img *Image) drawCircle(color color.Color, x, y, radius int) {
    	f := 1 - radius
    	dfx := 1
    	dfy := -2 * radius
    	xx := 0
    	yy := radius
    	img.Set(x, y+radius, color)
    	img.Set(x, y-radius, color)
    	img.drawHorizLine(color, x-radius, x+radius, y)
    	for xx < yy {
    		if f >= 0 {
    			yy--
    			dfy += 2
    			f += dfy
    		}
    		xx++
    		dfx += 2
    		f += dfx
    		img.drawHorizLine(color, x-xx, x+xx, y+yy)
    		img.drawHorizLine(color, x-xx, x+xx, y-yy)
    		img.drawHorizLine(color, x-yy, x+yy, y+xx)
    		img.drawHorizLine(color, x-yy, x+yy, y-xx)
    	}
    
    }
    
    func (img *Image) strikeThrough() {
    	r := 0
    	maxx := img.Bounds().Max.X
    	maxy := img.Bounds().Max.Y
    	y := rnd(maxy/3, maxy-maxy/3)
    	for x := 0; x < maxx; x += r {
    		r = rnd(1, img.dotsize/3)
    		y += rnd(-img.dotsize/2, img.dotsize/2)
    		if y <= 0 || y >= maxy {
    			y = rnd(maxy/3, maxy-maxy/3)
    		}
    		img.drawCircle(img.color, x, y, r)
    	}
    
    }
    
    func (img *Image) drawDigit(digit []byte, x, y int) {
    	skf := rand.Float64() * float64(rnd(-maxSkew, maxSkew))
    	xs := float64(x)
    	minr := img.dotsize / 2               // minumum radius
    	maxr := img.dotsize/2 + img.dotsize/4 // maximum radius
    	y += rnd(-minr, minr)
    	for yy := 0; yy < fontHeight; yy++ {
    		for xx := 0; xx < fontWidth; xx++ {
    			if digit[yy*fontWidth+xx] != blackChar {
    				continue
    			}
    			// Introduce random variations.
    			or := rnd(minr, maxr)
    			ox := x + (xx * img.dotsize) + rnd(0, or/2)
    			oy := y + (yy * img.dotsize) + rnd(0, or/2)
    			img.drawCircle(img.color, ox, oy, or)
    		}
    		xs += skf
    		x = int(xs)
    	}
    
    }
    
    func setRandomBrightness(c *color.NRGBA, max uint8) {
    	minc := min3(c.R, c.G, c.B)
    	maxc := max3(c.R, c.G, c.B)
    	if maxc > max {
    		return
    	}
    	n := rand.Intn(int(max-maxc)) - int(minc)
    	c.R = uint8(int(c.R) + n)
    	c.G = uint8(int(c.G) + n)
    	c.B = uint8(int(c.B) + n)
    
    }
    
    func min3(x, y, z uint8) (o uint8) {
    	o = x
    	if y < o {
    		o = y
    	}
    	if z < o {
    		o = z
    	}
    	return
    
    }
    
    func max3(x, y, z uint8) (o uint8) {
    	o = x
    	if y > o {
    		o = y
    	}
    	if z > o {
    		o = z
    	}
    	return
    
    }
    
    // rnd returns a random number in range [from, to].
    
    func rnd(from, to int) int {
    	//println(to+1-from)
    	return rand.Intn(to+1-from) + from
    
    }
    
    const (
    	// Standard length of uniuri string to achive ~95 bits of entropy.
    	StdLen = 16
    	// Length of uniurl string to achive ~119 bits of entropy, closest
    	// to what can be losslessly converted to UUIDv4 (122 bits).
    	UUIDLen = 20
    )
    
    // Standard characters allowed in uniuri string.
    
    var StdChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
    
    // New returns a new random string of the standard length, consisting of
    // standard characters.
    
    func New() string {
    	return NewLenChars(StdLen, StdChars)
    
    }
    
    // NewLen returns a new random string of the provided length, consisting of
    // standard characters.
    
    func NewLen(length int) string {
    	return NewLenChars(length, StdChars)
    
    }
    
    // NewLenChars returns a new random string of the provided length, consisting
    // of the provided byte slice of allowed characters (maximum 256).
    
    func NewLenChars(length int, chars []byte) string {
    	b := make([]byte, length)
    	r := make([]byte, length+(length/4)) // storage for random bytes.
    	clen := byte(len(chars))
    	maxrb := byte(256 - (256 % len(chars)))
    	i := 0
    	for {
    		if _, err := io.ReadFull(crand.Reader, r); err != nil {
    			panic("error reading from random source: " + err.Error())
    		}
    		for _, c := range r {
    			if c >= maxrb {
    				// Skip this number to avoid modulo bias.
    				continue
    			}
    			b[i] = chars[c%clen]
    			i++
    			if i == length {
    				return string(b)
    			}
    		}
    	}
    	panic("unreachable")
    
    }
    
    func pic(w http.ResponseWriter, req *http.Request) {
    	d := make([]byte, 4)
    	s := NewLen(4)
    	ss := ""
    	t := time.Now()
    	td := t.Unix()
    	// 清除超时验证码
    	for k :=range RegisterCode{
    		oldtt := RegisterCode[k]
    		if td - oldtt > 300  {
    			delete(RegisterCode,k);
    		}
    	}
    	d = []byte(s)
    	for v := range d {
    		d[v] %= 10
    		ss += strconv.FormatInt(int64(d[v]), 32)
    	}
    	RegisterCode[ss] = td
    
    	w.Header().Set("Content-Type", "image/png")
    	NewImage(d, 100, 40).WriteTo(w)
    	fmt.Println("验证码",ss,RegisterCode)
    
    }
    
    func validate(w http.ResponseWriter, req *http.Request) {
    	code := req.FormValue("code") //取值
    
    	result := NewJsondata()
    	if code == ""{
    		result.Status = false
    		result.Message = "请输入验证码"
    	}else {
    		t := time.Now()
    		td := t.Unix()
    		// 处理超时的数据
    		for k :=range RegisterCode{
    			oldtt := RegisterCode[k]
    			println(td,oldtt,td - oldtt)
    			if td - oldtt > 300  {
    				delete(RegisterCode,k);
    			}
    		}
    		_, status := RegisterCode[code]
    		if status{
    			result.Status = true
    			result.Message = "验证成功"
    			delete(RegisterCode,code);
    		}else {
    			result.Status = false
    			result.Message = "验证码不正确"
    		}
    	}
    	// 返回数据
    	bytes, _ := json.Marshal(result)
    	fmt.Fprint(w, string(bytes))
    }
    
    func main() {
    	http.HandleFunc("/register/pic", pic)
    	http.HandleFunc("/register/validate", validate)
    	s := &http.Server{
    		Addr:           ":8080",
    		ReadTimeout:    30 * time.Second,
    		WriteTimeout:   30 * time.Second,
    		MaxHeaderBytes: 1 << 20}
    	s.ListenAndServe()
    
    }
    

      


    
    
    From Hairui 转载请注明出处!谢谢
  • 相关阅读:
    公共控件
    winform 窗口 属性
    ADO
    笔记备忘
    常识 备忘
    Symbol
    Promise
    定义类 属性 方法 执行
    x is string str ======x is string 变量名
    ManualResetEvent多线程进行,全部完成后,回调
  • 原文地址:https://www.cnblogs.com/hairuipython/p/7323420.html
Copyright © 2020-2023  润新知