2024-07-12 20:32:33 +08:00
|
|
|
|
package handler
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
|
|
|
|
"image"
|
|
|
|
|
"image/png"
|
|
|
|
|
"net"
|
|
|
|
|
"net/http"
|
|
|
|
|
"picgo/corelib"
|
|
|
|
|
"picgo/corelib/captcha"
|
|
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func CaptchaHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
var (
|
|
|
|
|
res []byte
|
|
|
|
|
err error
|
|
|
|
|
)
|
|
|
|
|
captchaId := getCaptchaId(r)
|
2024-07-13 20:33:20 +08:00
|
|
|
|
corelib.Logger.Info("captchaHandler cid: ", captchaId)
|
2024-07-12 20:32:33 +08:00
|
|
|
|
if res, err = generateCaptcha(captchaId); err != nil {
|
|
|
|
|
corelib.WriteJsonResponse(w, 1030, "生产验证码失败", nil)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// 设置响应头
|
|
|
|
|
w.Header().Set("Content-Type", "image/png")
|
|
|
|
|
// 将图片文件内容写入响应
|
|
|
|
|
_, err = w.Write(res)
|
|
|
|
|
if err != nil {
|
|
|
|
|
http.Error(w, "Failed to serve image.", http.StatusInternalServerError)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// user agent + client ip md5 生成验证码key
|
|
|
|
|
func getCaptchaId(r *http.Request) string {
|
|
|
|
|
clientIP := GetRealIP(r)
|
|
|
|
|
userAgent := r.Header.Get("User-Agent")
|
|
|
|
|
return corelib.Md5Hash(clientIP + userAgent)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成验证码图片
|
|
|
|
|
func generateCaptcha(captchaId string) ([]byte, error) {
|
|
|
|
|
var (
|
|
|
|
|
b bytes.Buffer
|
|
|
|
|
img *image.RGBA
|
|
|
|
|
err error
|
|
|
|
|
)
|
|
|
|
|
if img, err = captcha.GenerateCaptcha(captchaId); err != nil {
|
|
|
|
|
corelib.Logger.Fatalln("生成验证码错误", err)
|
|
|
|
|
return nil, err
|
|
|
|
|
//return nil, corelib.CAPTCHA_GENERATE_ERROR
|
|
|
|
|
}
|
|
|
|
|
if err = png.Encode(&b, img); err != nil {
|
|
|
|
|
corelib.Logger.Fatalln("验证码encode错误", err)
|
|
|
|
|
return nil, err
|
|
|
|
|
//return nil, corelib.CAPTCHA_GENERATE_ERROR
|
|
|
|
|
}
|
|
|
|
|
return b.Bytes(), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetRealIP 获取用户的真实IP地址
|
|
|
|
|
func GetRealIP(r *http.Request) string {
|
|
|
|
|
// 检查 X-Forwarded-For 头
|
|
|
|
|
xff := r.Header.Get("X-Forwarded-For")
|
|
|
|
|
if xff != "" {
|
|
|
|
|
// X-Forwarded-For 头可以包含多个IP地址,取第一个
|
|
|
|
|
ips := strings.Split(xff, ",")
|
|
|
|
|
if len(ips) > 0 {
|
|
|
|
|
return strings.TrimSpace(ips[0])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查 X-Real-IP 头
|
|
|
|
|
xri := r.Header.Get("X-Real-IP")
|
|
|
|
|
if xri != "" {
|
|
|
|
|
return xri
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果没有这些头,则使用远程地址
|
|
|
|
|
ip, _, err := net.SplitHostPort(r.RemoteAddr)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return r.RemoteAddr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ip
|
|
|
|
|
}
|