picgo/handler/captcha.go

86 lines
1.9 KiB
Go
Raw Normal View History

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)
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
}