Go 语言做的几个验证码
1、http://www.oschina.net/code/snippet_173630_12006 :
效果:
源代码:
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
它比较强大,可以生成图片的验证码或者音频验证码。
Go 语言做的几个验证码的更多相关文章
- 用Go语言做产品半年的一些感觉
用Go语言做产品刚好半年,有一些感觉跟大家说道说道. 在使用Go之前,我常常想象,无法使用先进的Debug工具会对工作进度造成多么巨大的影响.甚至在Visual Studio的娇惯下认为,不能调试基本 ...
- 一步一步来做WebQQ机器人-(一)(验证码)
× Well done! 为了探究webqq的http请求流程和数据交互,我付出了很多心血. 写下这篇文章!!!这是我逝去的青春 系列写完之后我会把源码打包奉上~ ------我的征途是星辰大海 预计 ...
- [Windows Phone] 以多国语言做为开发前提 (1)
原文:[Windows Phone] 以多国语言做为开发前提 (1) ? 前言 在先前 TechDays 2013 的课程 [开发 Windows Phone 商务应用程式就是这麽快] 中,其中一个部 ...
- [Windows Phone] 以多国语言做为开发前提 (2)
原文:[Windows Phone] 以多国语言做为开发前提 (2) ? 前言 在先前的文章 [Windows Phone 开发 - 以多国语言做为开发前提 (1)] 中说明了简单的多国语言范例,今天 ...
- 用R语言 做回归分析
使用R做回归分析整体上是比较常规的一类数据分析内容,下面我们具体的了解用R语言做回归分析的过程. 首先,我们先构造一个分析的数据集 x<-data.frame(y=c(102,115,124,1 ...
- C语言做一个通讯录程序(在console里面运行)
最近复习C语言的时候看到网上有个C语言通讯录的小项目,于是看了下那个程序实现的大概的功能,然后自己也跟着做了个.代码还算简洁,贴上来给有需要的人. // // main.m // AdressBook ...
- 用C语言做一个横板过关类型的控制台游戏
前言:本教程是写给刚学会C语言基本语法不久的新生们. 因为在学习C语言途中,往往只能写控制台代码,而还能没接触到图形,也就基本碰不到游戏开发. 所以本教程希望可以给仍在学习C语言的新生们能提前感受到游 ...
- 为备考二级C语言做的代码练习---辅导资料《C语言经典编程282例》--(1)
因为二级考试的时候用的C语言编译器是VC++6.0 真是日了狗了 用这个编译器 这是我第2个C编译器吧,第一个用的是啊哈C编译器..第二个是VS++6.0 然后在win下用VS2013感觉挺不错的 毕 ...
- 为什么要用Go语言做后端
FMZ数字货币量化平台 www.fmz.com, 后端使用Go语言,这里是创始人Zero谈论使用Go语言所带了的便利.原帖地址:https://www.zhihu.com/question/27172 ...
随机推荐
- 超级内存NVDIMM:下一代数据中心存储关键技术
1.背景介绍 连接到互联网的设备数量不断增长,到2015年,将达到150亿之多.而数据中心的压力也随之增加,唯有采用新的技术才能进一步提升其效率和性能. 相比于HDD传统硬盘,固态硬盘大大增加了I/O ...
- 【原创】【ViewFlow+GridView】Parameter must be a descendant of this view问题分析
关于ViewFlow和GridView嵌套导致Parameter must be a descendant of this view问题的解决方案 [关于ViewFlow] ViewFlow是一款 ...
- C 中数组和指针的区别
联系: 1,一个通过数组和下标实现的表达式可等价地通过指针和偏移量实现. 2,当数组名传递给一个函数时,实际上传递的是该数组第一个元素的地址. 区别: 1,指针是一个变量,因此,在C语言中,语句pa= ...
- http://www.360doc.com/content/12/1014/00/7471983_241330790.shtml
http://www.360doc.com/content/12/1014/00/7471983_241330790.shtml
- 运行java -version报cannot restore segment prot after reloc: Permission denied
linux 安装jdk1.6后,运行java -version,没有出现相关的版本信息,而是出现了以下错误: dl failure on line 685Error: failed /usr/loca ...
- Android 获取最近应用的缩略图
最近有项需求是获取应用的缩略,用于在动画时显示.因此就对此块知识简要了解了一下. 在android中获取视频文件的缩略图有三种方法: 1.从媒体库中查询 新视频增加后需要SDCard重新扫描才能给新增 ...
- Ext的正则表达式
http://www.cnblogs.com/azai/archive/2010/12/31/1923140.html 今天看到一篇关于Extjs正则表达式比较系统的总结. 使用extJs时能常用 ...
- Python得到前面12个月的数据,Python得到现在时间 前一年的数据,
#Python 实现得到现在时间12个月前的每个月 # 假设现在的时间是2016年9月25日 #得到现在的时间 得到now等于2016年9月25日 now = datetime.datetime.no ...
- Finalization
1.what is the main disadvantage of garbage collection? Typically, garbage collection has certain dis ...
- 《OD学HBase》20160820
一.案例 微博: 微博内容: 关注用户和粉丝用户: 添加或移除关注用户 查看关注用户的微博内容 微博数据存储: 响应时间 秒级 无延迟 (1)mysql分布式 (2)hbase数据库 使用HBase数 ...