zoukankan      html  css  js  c++  java
  • Go 语言做的几个验证码

    1、http://www.oschina.net/code/snippet_173630_12006

    效果:

    image image

    image image image

    源代码:

       1: package main
       2:  
       3: import (
       4:     crand "crypto/rand"
       5:     "fmt"
       6:     "image"
       7:     "image/color"
       8:     "image/png"
       9:     "io"
      10:     "math/rand"
      11:     "net/http"
      12:     "strconv"
      13:     "time"
      14: )
      15:  
      16: const (
      17:     stdWidth  = 100
      18:     stdHeight = 40
      19:     maxSkew   = 2
      20: )
      21:  
      22: const (
      23:     fontWidth  = 5
      24:     fontHeight = 8
      25:     blackChar  = 1
      26: )
      27:  
      28: var font = [][]byte{
      29:     { // 0
      30:         0, 1, 1, 1, 0,
      31:         1, 0, 0, 0, 1,
      32:         1, 0, 0, 0, 1,
      33:         1, 0, 0, 0, 1,
      34:         1, 0, 0, 0, 1,
      35:         1, 0, 0, 0, 1,
      36:         1, 0, 0, 0, 1,
      37:         0, 1, 1, 1, 0},
      38:     { // 1
      39:         0, 0, 1, 0, 0,
      40:         0, 1, 1, 0, 0,
      41:         1, 0, 1, 0, 0,
      42:         0, 0, 1, 0, 0,
      43:         0, 0, 1, 0, 0,
      44:         0, 0, 1, 0, 0,
      45:         0, 0, 1, 0, 0,
      46:         1, 1, 1, 1, 1},
      47:     { // 2
      48:         0, 1, 1, 1, 0,
      49:         1, 0, 0, 0, 1,
      50:         0, 0, 0, 0, 1,
      51:         0, 0, 0, 1, 1,
      52:         0, 1, 1, 0, 0,
      53:         1, 0, 0, 0, 0,
      54:         1, 0, 0, 0, 0,
      55:         1, 1, 1, 1, 1},
      56:     { // 3
      57:         1, 1, 1, 1, 0,
      58:         0, 0, 0, 0, 1,
      59:         0, 0, 0, 1, 0,
      60:         0, 1, 1, 1, 0,
      61:         0, 0, 0, 1, 0,
      62:         0, 0, 0, 0, 1,
      63:         0, 0, 0, 0, 1,
      64:         1, 1, 1, 1, 0},
      65:     { // 4
      66:         1, 0, 0, 1, 0,
      67:         1, 0, 0, 1, 0,
      68:         1, 0, 0, 1, 0,
      69:         1, 0, 0, 1, 0,
      70:         1, 1, 1, 1, 1,
      71:         0, 0, 0, 1, 0,
      72:         0, 0, 0, 1, 0,
      73:         0, 0, 0, 1, 0},
      74:     { // 5
      75:         1, 1, 1, 1, 1,
      76:         1, 0, 0, 0, 0,
      77:         1, 0, 0, 0, 0,
      78:         1, 1, 1, 1, 0,
      79:         0, 0, 0, 0, 1,
      80:         0, 0, 0, 0, 1,
      81:         0, 0, 0, 0, 1,
      82:         1, 1, 1, 1, 0},
      83:     { // 6
      84:         0, 0, 1, 1, 1,
      85:         0, 1, 0, 0, 0,
      86:         1, 0, 0, 0, 0,
      87:         1, 1, 1, 1, 0,
      88:         1, 0, 0, 0, 1,
      89:         1, 0, 0, 0, 1,
      90:         1, 0, 0, 0, 1,
      91:         0, 1, 1, 1, 0},
      92:     { // 7
      93:         1, 1, 1, 1, 1,
      94:         0, 0, 0, 0, 1,
      95:         0, 0, 0, 0, 1,
      96:         0, 0, 0, 1, 0,
      97:         0, 0, 1, 0, 0,
      98:         0, 1, 0, 0, 0,
      99:         0, 1, 0, 0, 0,
     100:         0, 1, 0, 0, 0},
     101:     { // 8
     102:         0, 1, 1, 1, 0,
     103:         1, 0, 0, 0, 1,
     104:         1, 0, 0, 0, 1,
     105:         0, 1, 1, 1, 0,
     106:         1, 0, 0, 0, 1,
     107:         1, 0, 0, 0, 1,
     108:         1, 0, 0, 0, 1,
     109:         0, 1, 1, 1, 0},
     110:     { // 9
     111:         0, 1, 1, 1, 0,
     112:         1, 0, 0, 0, 1,
     113:         1, 0, 0, 0, 1,
     114:         1, 1, 0, 0, 1,
     115:         0, 1, 1, 1, 1,
     116:         0, 0, 0, 0, 1,
     117:         0, 0, 0, 0, 1,
     118:         1, 1, 1, 1, 0},
     119: }
     120:  
     121: type Image struct {
     122:     *image.NRGBA
     123:     color   *color.NRGBA
     124:     width   int //a digit width
     125:     height  int //a digit height
     126:     dotsize int
     127: }
     128:  
     129: func init() {
     130:     rand.Seed(int64(time.Second))
     131:  
     132: }
     133:  
     134: func NewImage(digits []byte, width, height int) *Image {
     135:     img := new(Image)
     136:     r := image.Rect(img.width, img.height, stdWidth, stdHeight)
     137:     img.NRGBA = image.NewNRGBA(r)
     138:     img.color = &color.NRGBA{
     139:         uint8(rand.Intn(129)),
     140:         uint8(rand.Intn(129)),
     141:         uint8(rand.Intn(129)),
     142:         0xFF}
     143:     // Draw background (10 random circles of random brightness)
     144:     img.calculateSizes(width, height, len(digits))
     145:     img.fillWithCircles(10, img.dotsize)
     146:     maxx := width - (img.width+img.dotsize)*len(digits) - img.dotsize
     147:     maxy := height - img.height - img.dotsize*2
     148:     x := rnd(img.dotsize*2, maxx)
     149:     y := rnd(img.dotsize*2, maxy)
     150:     // Draw digits.
     151:     for _, n := range digits {
     152:         img.drawDigit(font[n], x, y)
     153:         x += img.width + img.dotsize
     154:     }
     155:     // Draw strike-through line.
     156:     img.strikeThrough()
     157:     return img
     158:  
     159: }
     160:  
     161: func (img *Image) WriteTo(w io.Writer) (int64, error) {
     162:     return 0, png.Encode(w, img)
     163:  
     164: }
     165:  
     166: func (img *Image) calculateSizes(width, height, ncount int) {
     167:     // Goal: fit all digits inside the image.
     168:     var border int
     169:     if width > height {
     170:         border = height / 5
     171:     } else {
     172:         border = width / 5
     173:     }
     174:     // Convert everything to floats for calculations.
     175:     w := float64(width - border*2)  //268
     176:     h := float64(height - border*2) //48
     177:     // fw takes into account 1-dot spacing between digits.
     178:     fw := float64(fontWidth) + 1 //6
     179:     fh := float64(fontHeight)    //8
     180:     nc := float64(ncount)        //7
     181:     // Calculate the width of a single digit taking into account only the
     182:     // width of the image.
     183:     nw := w / nc //38
     184:     // Calculate the height of a digit from this width.
     185:     nh := nw * fh / fw //51
     186:     // Digit too high?
     187:     if nh > h {
     188:         // Fit digits based on height.
     189:         nh = h //nh = 44
     190:         nw = fw / fh * nh
     191:     }
     192:     // Calculate dot size.
     193:     img.dotsize = int(nh / fh)
     194:     // Save everything, making the actual width smaller by 1 dot to account
     195:     // for spacing between digits.
     196:     img.width = int(nw)
     197:     img.height = int(nh) - img.dotsize
     198:  
     199: }
     200:  
     201: func (img *Image) fillWithCircles(n, maxradius int) {
     202:     color := img.color
     203:     maxx := img.Bounds().Max.X
     204:     maxy := img.Bounds().Max.Y
     205:     for i := 0; i < n; i++ {
     206:         setRandomBrightness(color, 255)
     207:         r := rnd(1, maxradius)
     208:         img.drawCircle(color, rnd(r, maxx-r), rnd(r, maxy-r), r)
     209:     }
     210:  
     211: }
     212:  
     213: func (img *Image) drawHorizLine(color color.Color, fromX, toX, y int) {
     214:     for x := fromX; x <= toX; x++ {
     215:         img.Set(x, y, color)
     216:     }
     217:  
     218: }
     219:  
     220: func (img *Image) drawCircle(color color.Color, x, y, radius int) {
     221:     f := 1 - radius
     222:     dfx := 1
     223:     dfy := -2 * radius
     224:     xx := 0
     225:     yy := radius
     226:     img.Set(x, y+radius, color)
     227:     img.Set(x, y-radius, color)
     228:     img.drawHorizLine(color, x-radius, x+radius, y)
     229:     for xx < yy {
     230:         if f >= 0 {
     231:             yy--
     232:             dfy += 2
     233:             f += dfy
     234:         }
     235:         xx++
     236:         dfx += 2
     237:         f += dfx
     238:         img.drawHorizLine(color, x-xx, x+xx, y+yy)
     239:         img.drawHorizLine(color, x-xx, x+xx, y-yy)
     240:         img.drawHorizLine(color, x-yy, x+yy, y+xx)
     241:         img.drawHorizLine(color, x-yy, x+yy, y-xx)
     242:     }
     243:  
     244: }
     245:  
     246: func (img *Image) strikeThrough() {
     247:     r := 0
     248:     maxx := img.Bounds().Max.X
     249:     maxy := img.Bounds().Max.Y
     250:     y := rnd(maxy/3, maxy-maxy/3)
     251:     for x := 0; x < maxx; x += r {
     252:         r = rnd(1, img.dotsize/3)
     253:         y += rnd(-img.dotsize/2, img.dotsize/2)
     254:         if y <= 0 || y >= maxy {
     255:             y = rnd(maxy/3, maxy-maxy/3)
     256:         }
     257:         img.drawCircle(img.color, x, y, r)
     258:     }
     259:  
     260: }
     261:  
     262: func (img *Image) drawDigit(digit []byte, x, y int) {
     263:     skf := rand.Float64() * float64(rnd(-maxSkew, maxSkew))
     264:     xs := float64(x)
     265:     minr := img.dotsize / 2               // minumum radius
     266:     maxr := img.dotsize/2 + img.dotsize/4 // maximum radius
     267:     y += rnd(-minr, minr)
     268:     for yy := 0; yy < fontHeight; yy++ {
     269:         for xx := 0; xx < fontWidth; xx++ {
     270:             if digit[yy*fontWidth+xx] != blackChar {
     271:                 continue
     272:             }
     273:             // Introduce random variations.
     274:             or := rnd(minr, maxr)
     275:             ox := x + (xx * img.dotsize) + rnd(0, or/2)
     276:             oy := y + (yy * img.dotsize) + rnd(0, or/2)
     277:             img.drawCircle(img.color, ox, oy, or)
     278:         }
     279:         xs += skf
     280:         x = int(xs)
     281:     }
     282:  
     283: }
     284:  
     285: func setRandomBrightness(c *color.NRGBA, max uint8) {
     286:     minc := min3(c.R, c.G, c.B)
     287:     maxc := max3(c.R, c.G, c.B)
     288:     if maxc > max {
     289:         return
     290:     }
     291:     n := rand.Intn(int(max-maxc)) - int(minc)
     292:     c.R = uint8(int(c.R) + n)
     293:     c.G = uint8(int(c.G) + n)
     294:     c.B = uint8(int(c.B) + n)
     295:  
     296: }
     297:  
     298: func min3(x, y, z uint8) (o uint8) {
     299:     o = x
     300:     if y < o {
     301:         o = y
     302:     }
     303:     if z < o {
     304:         o = z
     305:     }
     306:     return
     307:  
     308: }
     309:  
     310: func max3(x, y, z uint8) (o uint8) {
     311:     o = x
     312:     if y > o {
     313:         o = y
     314:     }
     315:     if z > o {
     316:         o = z
     317:     }
     318:     return
     319:  
     320: }
     321:  
     322: // rnd returns a random number in range [from, to].
     323:  
     324: func rnd(from, to int) int {
     325:     //println(to+1-from)
     326:     return rand.Intn(to+1-from) + from
     327:  
     328: }
     329:  
     330: const (
     331:     // Standard length of uniuri string to achive ~95 bits of entropy.
     332:     StdLen = 16
     333:     // Length of uniurl string to achive ~119 bits of entropy, closest
     334:     // to what can be losslessly converted to UUIDv4 (122 bits).
     335:     UUIDLen = 20
     336: )
     337:  
     338: // Standard characters allowed in uniuri string.
     339:  
     340: var StdChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
     341:  
     342: // New returns a new random string of the standard length, consisting of
     343: // standard characters.
     344:  
     345: func New() string {
     346:     return NewLenChars(StdLen, StdChars)
     347:  
     348: }
     349:  
     350: // NewLen returns a new random string of the provided length, consisting of
     351: // standard characters.
     352:  
     353: func NewLen(length int) string {
     354:     return NewLenChars(length, StdChars)
     355:  
     356: }
     357:  
     358: // NewLenChars returns a new random string of the provided length, consisting
     359: // of the provided byte slice of allowed characters (maximum 256).
     360:  
     361: func NewLenChars(length int, chars []byte) string {
     362:     b := make([]byte, length)
     363:     r := make([]byte, length+(length/4)) // storage for random bytes.
     364:     clen := byte(len(chars))
     365:     maxrb := byte(256 - (256 % len(chars)))
     366:     i := 0
     367:     for {
     368:         if _, err := io.ReadFull(crand.Reader, r); err != nil {
     369:             panic("error reading from random source: " + err.Error())
     370:         }
     371:         for _, c := range r {
     372:             if c >= maxrb {
     373:                 // Skip this number to avoid modulo bias.
     374:                 continue
     375:             }
     376:             b[i] = chars[c%clen]
     377:             i++
     378:             if i == length {
     379:                 return string(b)
     380:             }
     381:         }
     382:     }
     383:     panic("unreachable")
     384:  
     385: }
     386:  
     387: func pic(w http.ResponseWriter, req *http.Request) {
     388:     d := make([]byte, 4)
     389:     s := NewLen(4)
     390:     ss := ""
     391:     d = []byte(s)
     392:     for v := range d {
     393:         d[v] %= 10
     394:         ss += strconv.FormatInt(int64(d[v]), 32)
     395:     }
     396:     w.Header().Set("Content-Type", "image/png")
     397:     NewImage(d, 100, 40).WriteTo(w)
     398:     fmt.Println(ss)
     399:  
     400: }
     401:  
     402: func index(w http.ResponseWriter, req *http.Request) {
     403:     str := "<meta charset="utf-8"><h3>golang 图片验证码例子</h3><img border="1" src="/pic" alt="图片验证码" onclick="this.src='/pic'" />"
     404:     w.Header().Set("Content-Type", "text/html")
     405:     w.Write([]byte(str))
     406:  
     407: }
     408:  
     409: func main() {
     410:     http.HandleFunc("/pic", pic)
     411:     http.HandleFunc("/", index)
     412:     s := &http.Server{
     413:         Addr:           ":8080",
     414:         ReadTimeout:    30 * time.Second,
     415:         WriteTimeout:   30 * time.Second,
     416:         MaxHeaderBytes: 1 << 20}
     417:     s.ListenAndServe()
     418:  
     419: }

     

    2、https://github.com/dchest/captcha 

    它比较强大,可以生成图片的验证码或者音频验证码。

    image image

    image image image

  • 相关阅读:
    常见HTTP状态码
    Spring MVC 原理小结
    RESTful API
    java:IO流学习小结
    理解 Statement 和 PreparedStatement
    Hibernate缓存原理与策略
    APP运营
    网站常见术语
    php常见术语
    运维------术语名词
  • 原文地址:https://www.cnblogs.com/ghj1976/p/3392847.html
Copyright © 2011-2022 走看看