|
| 1 | +package teawaf |
| 2 | + |
| 3 | +import ( |
| 4 | + "bytes" |
| 5 | + "encoding/base64" |
| 6 | + "fmt" |
| 7 | + "github.com/TeaWeb/code/teawaf/requests" |
| 8 | + "github.com/dchest/captcha" |
| 9 | + "github.com/iwind/TeaGo/logs" |
| 10 | + stringutil "github.com/iwind/TeaGo/utils/string" |
| 11 | + "net/http" |
| 12 | + "time" |
| 13 | +) |
| 14 | + |
| 15 | +var captchaValidator = &CaptchaValidator{} |
| 16 | + |
| 17 | +type CaptchaValidator struct { |
| 18 | +} |
| 19 | + |
| 20 | +func (this *CaptchaValidator) Run(request *requests.Request, writer http.ResponseWriter) { |
| 21 | + if request.Method == http.MethodPost && len(request.FormValue("TEAWEB_WAF_CAPTCHA_ID")) > 0 { |
| 22 | + this.validate(request, writer) |
| 23 | + } else { |
| 24 | + this.show(request, writer) |
| 25 | + } |
| 26 | +} |
| 27 | + |
| 28 | +func (this *CaptchaValidator) show(request *requests.Request, writer http.ResponseWriter) { |
| 29 | + // show captcha |
| 30 | + captchaId := captcha.NewLen(6) |
| 31 | + buf := bytes.NewBuffer([]byte{}) |
| 32 | + err := captcha.WriteImage(buf, captchaId, 200, 100) |
| 33 | + if err != nil { |
| 34 | + logs.Error(err) |
| 35 | + return |
| 36 | + } |
| 37 | + |
| 38 | + _, _ = writer.Write([]byte(`<!DOCTYPE html> |
| 39 | +<html> |
| 40 | +<head> |
| 41 | + <title>Verify Yourself</title> |
| 42 | +</head> |
| 43 | +<body> |
| 44 | +<form method="POST"> |
| 45 | + <input type="hidden" name="TEAWEB_WAF_CAPTCHA_ID" value="` + captchaId + `"/> |
| 46 | + <img src="data:image/png;base64, ` + base64.StdEncoding.EncodeToString(buf.Bytes()) + `"/>` + ` |
| 47 | + <div> |
| 48 | + <p>Input verify code above:</p> |
| 49 | + <input type="text" name="TEAWEB_WAF_CAPTCHA_CODE" maxlength="6" size="18" autocomplete="off" z-index="1" style="font-size:16px;line-height:24px; letter-spacing: 15px; padding-left: 4px"/> |
| 50 | + </div> |
| 51 | + <div> |
| 52 | + <button type="submit" onclick="window.location = '/webhook'" style="line-height:24px;margin-top:10px">Verify Yourself</button> |
| 53 | + </div> |
| 54 | +</form> |
| 55 | +</body> |
| 56 | +</html>`)) |
| 57 | +} |
| 58 | + |
| 59 | +func (this *CaptchaValidator) validate(request *requests.Request, writer http.ResponseWriter) (allow bool) { |
| 60 | + captchaId := request.FormValue("TEAWEB_WAF_CAPTCHA_ID") |
| 61 | + if len(captchaId) > 0 { |
| 62 | + captchaCode := request.FormValue("TEAWEB_WAF_CAPTCHA_CODE") |
| 63 | + if captcha.VerifyString(captchaId, captchaCode) { |
| 64 | + // set cookie |
| 65 | + timestamp := fmt.Sprintf("%d", time.Now().Unix()+CaptchaSeconds) |
| 66 | + m := stringutil.Md5(captchaSalt + timestamp) |
| 67 | + http.SetCookie(writer, &http.Cookie{ |
| 68 | + Name: "TEAWEB_WAF_CAPTCHA", |
| 69 | + Value: m + timestamp, |
| 70 | + MaxAge: CaptchaSeconds, |
| 71 | + Path: "/", // all of dirs |
| 72 | + }) |
| 73 | + |
| 74 | + rawURL := request.URL.Query().Get("url") |
| 75 | + http.Redirect(writer, request.Raw(), rawURL, http.StatusSeeOther) |
| 76 | + |
| 77 | + return false |
| 78 | + } else { |
| 79 | + http.Redirect(writer, request.Raw(), request.URL.String(), http.StatusSeeOther) |
| 80 | + } |
| 81 | + } |
| 82 | + |
| 83 | + return true |
| 84 | +} |
0 commit comments