package waf import ( "bytes" "encoding/base64" "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs" "github.com/TeaOSLab/EdgeNode/internal/ttlcache" "github.com/TeaOSLab/EdgeNode/internal/utils" "github.com/TeaOSLab/EdgeNode/internal/utils/jsonutils" "github.com/TeaOSLab/EdgeNode/internal/waf/requests" "github.com/dchest/captcha" "github.com/iwind/TeaGo/logs" "github.com/iwind/TeaGo/types" "net/http" "strconv" "strings" "time" ) var captchaValidator = NewCaptchaValidator() type CaptchaValidator struct { } func NewCaptchaValidator() *CaptchaValidator { return &CaptchaValidator{} } func (this *CaptchaValidator) Run(request requests.Request, writer http.ResponseWriter) { var info = request.WAFRaw().URL.Query().Get("info") if len(info) == 0 { writer.WriteHeader(http.StatusBadRequest) _, _ = writer.Write([]byte("invalid request")) return } m, err := utils.SimpleDecryptMap(info) if err != nil { _, _ = writer.Write([]byte("invalid request")) return } timestamp := m.GetInt64("timestamp") if timestamp < time.Now().Unix()-600 { // 10分钟之后信息过期 http.Redirect(writer, request.WAFRaw(), m.GetString("url"), http.StatusTemporaryRedirect) return } var actionConfig = &CaptchaAction{} err = jsonutils.MapToObject(m.GetMap("action"), actionConfig) if err != nil { http.Redirect(writer, request.WAFRaw(), m.GetString("url"), http.StatusTemporaryRedirect) return } var setId = m.GetInt64("setId") var originURL = m.GetString("url") if request.WAFRaw().Method == http.MethodPost && len(request.WAFRaw().FormValue("GOEDGE_WAF_CAPTCHA_ID")) > 0 { this.validate(actionConfig, m.GetInt("maxFails"), m.GetInt("failBlockTimeout"), m.GetInt64("policyId"), m.GetInt64("groupId"), setId, originURL, request, writer) } else { this.show(actionConfig, request, writer) } } func (this *CaptchaValidator) show(actionConfig *CaptchaAction, request requests.Request, writer http.ResponseWriter) { // show captcha captchaId := captcha.NewLen(6) buf := bytes.NewBuffer([]byte{}) err := captcha.WriteImage(buf, captchaId, 200, 100) if err != nil { logs.Error(err) return } var lang = actionConfig.Language if len(lang) == 0 { acceptLanguage := request.WAFRaw().Header.Get("Accept-Language") if len(acceptLanguage) > 0 { langIndex := strings.Index(acceptLanguage, ",") if langIndex > 0 { lang = acceptLanguage[:langIndex] } } } if len(lang) == 0 { lang = "en-US" } var msgTitle = "" var msgPrompt = "" var msgButtonTitle = "" var msgRequestId = "" switch lang { case "en-US": msgTitle = "Verify Yourself" msgPrompt = "Input verify code above:" msgButtonTitle = "Verify Yourself" msgRequestId = "Request ID" case "zh-CN": msgTitle = "身份验证" msgPrompt = "请输入上面的验证码" msgButtonTitle = "提交验证" msgRequestId = "请求ID" default: msgTitle = "Verify Yourself" msgPrompt = "Input verify code above:" msgButtonTitle = "Verify Yourself" msgRequestId = "Request ID" } writer.Header().Set("Content-Type", "text/html; charset=utf-8") _, _ = writer.Write([]byte(`