添加图片验证码方法

This commit is contained in:
zhucheer 2019-11-12 16:53:29 +08:00
parent 4d63aba95b
commit 595b233217
16 changed files with 15639 additions and 72 deletions

3
.gitignore vendored
View File

@ -1 +1,2 @@
/.idea
/.idea
/vendor

View File

@ -38,6 +38,10 @@ func (c *Context) ResponseWrite(b []byte) error {
return err
}
func (c *Context) ResponseHeader() http.Header {
return c.response.Header()
}
func (c *Context) Header() http.Header {
return c.request.Header
}

35
captcha/captcha.go Normal file
View File

@ -0,0 +1,35 @@
package captcha
import (
"gitee.com/zhucheer/orange/app"
"gitee.com/zhucheer/orange/utils"
)
var captchaSessionName = "ORANGE-CAPTCHA"
func init() {
ranTag := utils.ShortTag(utils.GetRandStr(2), 1)
captchaSessionName += ranTag
}
func CaptchaImgShow(c *app.Context, n int, size ...int) error {
text := utils.GetRandStr(n)
textMd5 := utils.Md5ToString(text)
width := 180
height := 60
if len(size) >= 2 {
width = size[0]
height = size[1]
}
c.Session().Set(captchaSessionName, textMd5)
imgByte := ImgText(width, height, text)
c.ResponseHeader().Set("Content-Type", "image/png")
return c.ResponseWrite(imgByte)
}
func CaptchaVerify(code string) {
}

15356
captcha/comic.go Normal file

File diff suppressed because it is too large Load Diff

99
captcha/imgcode.go Normal file
View File

@ -0,0 +1,99 @@
package captcha
import (
"bytes"
"github.com/fogleman/gg"
"github.com/golang/freetype/truetype"
"golang.org/x/image/font"
"math/rand"
)
func ImgText(width, height int, text string) (b []byte) {
textLen := len(text)
dc := gg.NewContext(width, height)
bgR, bgG, bgB, bgA := getRandColorRange(240, 255)
dc.SetRGBA255(bgR, bgG, bgB, bgA)
dc.Clear()
// 干扰线
for i := 0; i < 10; i++ {
x1, y1 := getRandPos(width, height)
x2, y2 := getRandPos(width, height)
r, g, b, a := getRandColor(255)
w := float64(rand.Intn(3) + 1)
dc.SetRGBA255(r, g, b, a)
dc.SetLineWidth(w)
dc.DrawLine(x1, y1, x2, y2)
dc.Stroke()
}
fontSize := float64(height/2) + 5
face := loadFontFace(fontSize)
dc.SetFontFace(face)
for i := 0; i < len(text); i++ {
r, g, b, _ := getRandColor(100)
dc.SetRGBA255(r, g, b, 255)
fontPosX := float64(width/textLen*i) + fontSize*0.6
writeText(dc, text[i:i+1], float64(fontPosX), float64(height/2))
}
buffer := bytes.NewBuffer(nil)
dc.EncodePNG(buffer)
b = buffer.Bytes()
return
}
// 渲染文字
func writeText(dc *gg.Context, text string, x, y float64) {
xfload := 5 - rand.Float64()*10 + x
yfload := 5 - rand.Float64()*10 + y
radians := 40 - rand.Float64()*80
dc.RotateAbout(gg.Radians(radians), x, y)
dc.DrawStringAnchored(text, xfload, yfload, 0.2, 0.5)
dc.RotateAbout(-1*gg.Radians(radians), x, y)
dc.Stroke()
}
// 随机坐标
func getRandPos(width, height int) (x float64, y float64) {
x = rand.Float64() * float64(width)
y = rand.Float64() * float64(height)
return x, y
}
// 随机颜色
func getRandColor(maxColor int) (r, g, b, a int) {
r = int(uint8(rand.Intn(maxColor)))
g = int(uint8(rand.Intn(maxColor)))
b = int(uint8(rand.Intn(maxColor)))
a = int(uint8(rand.Intn(255)))
return r, g, b, a
}
// 随机颜色范围
func getRandColorRange(miniColor, maxColor int) (r, g, b, a int) {
if miniColor > maxColor {
miniColor = 0
maxColor = 255
}
r = int(uint8(rand.Intn(maxColor-miniColor) + miniColor))
g = int(uint8(rand.Intn(maxColor-miniColor) + miniColor))
b = int(uint8(rand.Intn(maxColor-miniColor) + miniColor))
a = int(uint8(rand.Intn(maxColor-miniColor) + miniColor))
return r, g, b, a
}
// 加载字体
func loadFontFace(points float64) font.Face {
f, err := truetype.Parse(COMICSAN)
if err != nil {
panic(err)
}
face := truetype.NewFace(f, &truetype.Options{
Size: points,
})
return face
}

View File

@ -8,7 +8,6 @@ import (
var Config = cfg.New("")
func init() {
path := flag.String("config", "./config/config.toml", "config file path")
flag.Parse()

View File

@ -1,39 +0,0 @@
[app]
name = "orange"
key = "sfdsfsfsfsfsfsfsfs"
logger_level = "info"
httpAddr = "127.0.0.1"
httpPort = 8088
maxBody = 2096157
csrfVerify = false
[app.logger]
level = "INFO"
type = "text"
path = ""
syncInterval = 2
[app.session]
isOpen = true
timeout = 1800
[app.upload]
maxSize = 2096157
ext = ["jpg","gif"]
[database]
initCap = 2
maxCap = 5
idleTimeout = 5
debug = true
[database.mysql]
[database.mysql.default]
addr = "192.168.137.100:3306"
username = "zhuqi"
password = "123456"
dbname = "weixin"
[database.redis]
[database.redis.default]
addr = "192.168.137.101:6379"
password = "rw:Ql46"
dbnum = 5
[database.redis.dxx]
addr = "192.168.137.100:6379"
dbnum = 7

5
go.mod
View File

@ -3,8 +3,11 @@ module gitee.com/zhucheer/orange
go 1.12
require (
gitee.com/zhucheer/cfg v0.0.3
gitee.com/zhucheer/cfg v0.0.4
github.com/fogleman/gg v1.3.0
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/gomodule/redigo v2.0.0+incompatible
github.com/jinzhu/gorm v1.9.11
github.com/zhuCheer/pool v0.2.1
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
)

8
go.sum
View File

@ -4,6 +4,8 @@ cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU=
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
gitee.com/zhucheer/cfg v0.0.3 h1:MVwFzzmWHzpXWk6+rm0DkswAm4zYzusubDQnH5J58bc=
gitee.com/zhucheer/cfg v0.0.3/go.mod h1:c4gh5xN7OKIPMJPTCUN8X/br/TguQcHgzcU6ode1Fc0=
gitee.com/zhucheer/cfg v0.0.4 h1:KfWWhKVaRhqDxsmeDaFk6gTIACl4UXGBGGGpb9LHUkU=
gitee.com/zhucheer/cfg v0.0.4/go.mod h1:c4gh5xN7OKIPMJPTCUN8X/br/TguQcHgzcU6ode1Fc0=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
@ -21,6 +23,8 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
@ -30,6 +34,8 @@ github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@ -91,6 +97,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=

29
main.go
View File

@ -3,14 +3,16 @@ package main
import (
"bytes"
"crypto/md5"
"crypto/rand"
"encoding/hex"
"fmt"
"github.com/astaxie/beego/utils"
"io/ioutil"
r "math/rand"
"os"
"os/exec"
"runtime"
"strings"
"time"
)
func main() {
@ -177,12 +179,35 @@ func execShell(shell string) (stdout string, stderr string) {
}
func getRandAppKey() string {
randByte := utils.RandomCreateBytes(24)
randByte := RandomCreateBytes(24)
h := md5.New()
h.Write(randByte)
return hex.EncodeToString(h.Sum(nil))
}
var alphaNum = []byte(`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`)
// RandomCreateBytes generate random []byte by specify chars.
func RandomCreateBytes(n int, alphabets ...byte) []byte {
if len(alphabets) == 0 {
alphabets = alphaNum
}
var bytes = make([]byte, n)
var randBy bool
if num, err := rand.Read(bytes); num != n || err != nil {
r.Seed(time.Now().UnixNano())
randBy = true
}
for i, b := range bytes {
if randBy {
bytes[i] = alphabets[r.Intn(len(alphabets))]
} else {
bytes[i] = alphabets[b%byte(len(alphabets))]
}
}
return bytes
}
var maingoTpl = `
package main

View File

@ -2,6 +2,7 @@ package controller
import (
"gitee.com/zhucheer/orange/app"
"gitee.com/zhucheer/orange/captcha"
)
func Welcome(c *app.Context) error {
@ -30,3 +31,7 @@ func Upload(c *app.Context) error {
"info": "upload success",
})
}
func Captcha(c *app.Context) error {
return captcha.CaptchaImgShow(c, 4)
}

View File

@ -17,6 +17,8 @@ func (s *Route) ServeMux() {
})
commonGp.ALL("/upload", controller.Upload)
commonGp.GET("/captcha", controller.Captcha)
}
authGp := app.GroupRouter("/auth", middleware.NewAuth())

View File

@ -1,17 +1,3 @@
// Copyright 2014 beego Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package session
import (

View File

@ -1,17 +1,3 @@
// Copyright 2014 beego Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package session
import (

49
utils/hash.go Normal file
View File

@ -0,0 +1,49 @@
package utils
import (
"crypto/md5"
"fmt"
"strconv"
)
func Md5ToString(str string) string {
md5str := fmt.Sprintf("%x", md5.Sum([]byte(str)))
return md5str
}
func ShortTag(longstr string, number int) string {
baseVal := 0x3FFFFFFF
indexVal := 0x0000003D
charset := []byte("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
if number < 1 || number > 4 {
number = 1
}
key := "orange"
urlhash := Md5ToString(key + longstr)
len := len(urlhash)
var hexcc int64
var short_url []byte
var result [4]string
for i := 0; i < 4; i++ {
urlhash_piece := Substr(urlhash, i*len/4, len/4)
hexDec, _ := strconv.ParseInt(urlhash_piece, 16, 64)
hexcc = hexDec & int64(baseVal)
var index int64
short_url = []byte{}
for j := 0; j < 6; j++ {
//将得到的值与0x0000003d,3d为61即charset的坐标最大值
index = hexcc & int64(indexVal)
short_url = append(short_url, charset[index])
//循环完以后将hex右移5位
hexcc = hexcc >> 5
}
result[i] = string(short_url)
}
return result[number]
}

48
utils/text.go Normal file
View File

@ -0,0 +1,48 @@
package utils
import "math/rand"
func GetRandStr(n int) (randStr string) {
// 默认去掉了容易混淆的字符oOLl和数字01要添加请使用addChars参数
chars := "ABCDEFGHIJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789"
charsLen := len(chars)
if n > 10 {
n = 10
}
for i := 0; i < n; i++ {
randIndex := rand.Intn(charsLen)
randStr += chars[randIndex : randIndex+1]
}
return randStr
}
// Substr字符串截取
func Substr(str string, start int, length int) string {
rs := []rune(str)
rl := len(rs)
end := 0
if start < 0 {
start = rl - 1 + start
}
end = start + length
if start > end {
start, end = end, start
}
if start < 0 {
start = 0
}
if start > rl {
start = rl
}
if end < 0 {
end = 0
}
if end > rl {
end = rl
}
return string(rs[start:end])
}