• 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

  • 相关阅读:
    UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design
    UVa 1658 (拆点法 最小费用流) Admiral
    UVa 11082 (网络流建模) Matrix Decompressing
    UVa 753 (二分图最大匹配) A Plug for UNIX
    UVa 1451 (数形结合 单调栈) Average
    UVa 1471 (LIS变形) Defense Lines
    UVa 11572 (滑动窗口) Unique Snowflakes
    UVa 1606 (极角排序) Amphiphilic Carbon Molecules
    UVa 11054 Wine trading in Gergovia
    UVa 140 (枚举排列) Bandwidth
  • 原文地址:https://www.cnblogs.com/ghj1976/p/3392847.html
Copyright © 2020-2023  润新知