package gocaptcha import ( "app.yhyue.com/moapp/jybase/go-xweb/httpsession" "app.yhyue.com/moapp/jybase/redis" "fmt" "image/color" "log" "math/rand" "net/http" "time" ) // 图形验证码大小 const ( dx = 200 dy = 80 fontSize = 75 Rn = 1 CollectNum = 100 Expiration = 10 * time.Minute ) // 生成的字符集 var ( TextCharacters = []rune("ACDEFGHJKLMNPQRSTUVWXY2456789") globalStore = NewMemoryStore(CollectNum, Expiration) ) // 初始化字体文件 func InitCaptcha() { err := SetFontPath("./fonts/") if err != nil { log.Println(err) } } // RandText 生成随机字体. func RandText(num int) string { textNum := len(TextCharacters) text := make([]rune, num) for i := 0; i < num; i++ { text[i] = TextCharacters[rand.Intn(textNum)] } return string(text) } // RandLightColor 随机生成浅色底色. func RandLightColor(n int) color.RGBA { // 为每个颜色分量生成一个128到255之间的随机数 red := rand.Intn(100/n) + 156 + (100 - 100/n) green := rand.Intn(100/n) + 156 + (100 - 100/n) blue := rand.Intn(100/n) + 156 + (100 - 100/n) // Alpha 通道设置为完全不透明 a := uint8(rand.Intn(8) + 247) return color.RGBA{R: uint8(red), G: uint8(green), B: uint8(blue), A: a} } func Get(sess *httpsession.Session, checkCode string, w http.ResponseWriter, r *http.Request) { code := RandText(4) log.Println(code) cacheKey := fmt.Sprintf("captcha_times_%s", sess.Id()) var ( // 计次数 times = redis.GetInt("other", cacheKey) ttl = redis.GetTTL("other", cacheKey) rn = times%6 + 1 //跳色 cc = RandLightColor(rn) // ) // cc.A = uint8(rand.Intn(10) + 245) captchaImage := New(dx, dy, cc). DrawBorder(RandDeepColor()) if times < 3 { captchaImage = captchaImage.DrawNoise(NoiseDensityLower, NewPointNoiseDrawer(), rn). DrawNoise(NoiseDensityHigh, NewTextNoiseDrawer(42), rn). DrawLine(NewBeeline(), RandDeepColor()). DrawText(NewTwistTextDrawer(fontSize, 15, 0.04), code) } else if times < 6 { captchaImage = captchaImage.DrawNoise(NoiseDensityLower, NewPointNoiseDrawer(), rn). DrawNoise(NoiseDensityHigh, NewTextNoiseDrawer(43), rn). DrawLine(NewBeeline(), RandDeepColor()). DrawText(NewTwistTextDrawer(fontSize, 14, 0.03), code). DrawBlur(NewGaussianBlur(), 2, 0.15) } else if times < 10 { captchaImage = captchaImage.DrawNoise(NoiseDensityLower, NewPointNoiseDrawer(), rn). DrawNoise(NoiseDensityHigh, NewTextNoiseDrawer(45), rn). DrawLine(NewBeeline(), RandDeepColor()). DrawText(NewTwistTextDrawer(fontSize, 18, 0.04), code). DrawLine(NewBeeline(), RandDeepColor()). DrawBlur(NewGaussianBlur(), 2, 0.41) } else { captchaImage = captchaImage.DrawNoise(NoiseDensityHigh, NewTextNoiseDrawer(50), rn). DrawNoise(NoiseDensityLower, NewPointNoiseDrawer(), rn). DrawLine(NewBezier3DLine(), RandLightColor(rn)). DrawLine(NewBeeline(), RandDeepColor()). DrawText(NewTwistTextDrawer(fontSize, 18, 0.04), code). DrawBlur(NewGaussianBlur(), 2, 0.44) } if captchaImage.Error != nil { log.Println(captchaImage.Error) return } if times == 0 { ttl = 24 * 60 * 60 } //计次 times++ globalStore.Set(code, RandomDigits(len([]rune(code)))) //b := VerifyString(code, code) //fmt.Println(b) redis.Put("other", cacheKey, times, int(ttl)) sess.Set(checkCode, code) w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") w.Header().Set("Pragma", "no-cache") w.Header().Set("Expires", "0") w.Header().Set("Content-Type", "image/png") _ = captchaImage.Encode(w, ImageFormatJpeg) }