添加图片验证码方法
This commit is contained in:
parent
4d63aba95b
commit
595b233217
|
@ -1 +1,2 @@
|
|||
/.idea
|
||||
/.idea
|
||||
/vendor
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
}
|
|
@ -8,7 +8,6 @@ import (
|
|||
var Config = cfg.New("")
|
||||
|
||||
func init() {
|
||||
|
||||
path := flag.String("config", "./config/config.toml", "config file path")
|
||||
flag.Parse()
|
||||
|
||||
|
|
|
@ -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
5
go.mod
|
@ -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
8
go.sum
|
@ -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
29
main.go
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ func (s *Route) ServeMux() {
|
|||
})
|
||||
|
||||
commonGp.ALL("/upload", controller.Upload)
|
||||
|
||||
commonGp.GET("/captcha", controller.Captcha)
|
||||
}
|
||||
|
||||
authGp := app.GroupRouter("/auth", middleware.NewAuth())
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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]
|
||||
|
||||
}
|
|
@ -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])
|
||||
}
|
Loading…
Reference in New Issue