123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- package service
- import (
- "context"
- "crypto/md5"
- "encoding/hex"
- "fmt"
- "math"
- "math/rand"
- "strconv"
- "strings"
- "go-common/app/interface/main/answer/model"
- "go-common/library/log"
- "github.com/pkg/errors"
- )
- // preProcess getGeetestChal
- func (s *Service) preProcess(c context.Context, mid int64, ip, clientType string, newCaptcha int) (res *model.ProcessRes, err error) {
- var pre string
- res = &model.ProcessRes{}
- gc, geeType := s.geetestDao.GeeConfig(clientType, s.c.Geetest)
- res.CaptchaID = gc.CaptchaID
- res.NewCaptcha = newCaptcha
- if pre, err = s.geetestDao.PreProcess(c, mid, ip, geeType, gc, newCaptcha); err != nil || pre == "" {
- log.Error("s.geetestDao.PreProcess(%d) err(%v)", mid, err)
- randOne := md5.Sum([]byte(strconv.Itoa(rand.Intn(100))))
- randTwo := md5.Sum([]byte(strconv.Itoa(rand.Intn(100))))
- challenge := hex.EncodeToString(randOne[:]) + hex.EncodeToString(randTwo[:])[0:2]
- res.Challenge = challenge
- err = nil
- return
- }
- res.Success = 1
- slice := md5.Sum([]byte(pre + gc.PrivateKEY))
- res.Challenge = hex.EncodeToString(slice[:])
- return
- }
- // validate recheck the seccode
- func (s *Service) validate(c context.Context, challenge, validate, seccode, clientType, ip string, success int, mid int64) (stat bool) {
- if len(validate) != 32 {
- log.Error("s.Validate(%s,%s,%s,%d) err(validate not eq 32byte)", challenge, validate, seccode, mid)
- stat = s.failbackValidate(c, challenge, validate, seccode)
- log.Info("s.failbackValidate(%s,%s,%s,%d), stat(%t)", challenge, validate, seccode, mid, stat)
- return
- }
- if success != 1 {
- slice := md5.Sum([]byte(challenge))
- stat = hex.EncodeToString(slice[:]) == validate
- return
- }
- gc, geeType := s.geetestDao.GeeConfig(clientType, s.c.Geetest)
- slice := md5.Sum([]byte(gc.PrivateKEY + "geetest" + challenge))
- if hex.EncodeToString(slice[:]) != validate {
- log.Error("s.Validate(%s,%s,%s,%d) err(challenge not found)", challenge, validate, seccode, mid)
- return
- }
- res, err := s.geetestDao.Validate(c, challenge, seccode, geeType, ip, gc.CaptchaID, mid)
- if err != nil {
- if errors.Cause(err) == context.DeadlineExceeded { // for geetest timeout
- stat = true
- return
- }
- log.Error("s.geetestDao.Validate(%d) err(%v)", mid, err)
- return
- }
- slice = md5.Sum([]byte(seccode))
- stat = hex.EncodeToString(slice[:]) == res.Seccode
- return
- }
- //failbackValidate geetest failback model.
- func (s *Service) failbackValidate(c context.Context, challenge, validate, seccode string) bool {
- varr := strings.Split(validate, "_")
- if len(varr) < 3 {
- return false
- }
- encodeAns := varr[0]
- encodeFbii := varr[1]
- encodeIgi := varr[2]
- decodeAns := s.decodeResponse(challenge, encodeAns)
- decodeFbii := s.decodeResponse(challenge, encodeFbii)
- decodeIgi := s.decodeResponse(challenge, encodeIgi)
- return s.validateFailImage(decodeAns, decodeFbii, decodeIgi)
- }
- func (s *Service) decodeResponse(challenge, userresponse string) (res int) {
- if len(userresponse) > 100 {
- return
- }
- digits := []int{1, 2, 5, 10, 50}
- key := make(map[rune]int)
- for _, i := range challenge {
- if _, exist := key[i]; exist {
- continue
- }
- value := digits[len(key)%5]
- key[i] = value
- }
- for _, i := range userresponse {
- res += key[i]
- }
- res -= s.decodeRandBase(challenge)
- return
- }
- func (s *Service) decodeRandBase(challenge string) int {
- baseStr := challenge[32:]
- var tempList []int
- for _, char := range baseStr {
- tempChar := int(char)
- result := tempChar - 48
- if tempChar > 57 {
- result = tempChar - 87
- }
- tempList = append(tempList, result)
- }
- return tempList[0]*36 + tempList[1]
- }
- func (s *Service) md5Encode(values []byte) string {
- return fmt.Sprintf("%x", md5.Sum(values))
- }
- func (s *Service) validateFailImage(ans, fullBgIndex, imgGrpIndex int) bool {
- var thread float64 = 3
- fullBg := s.md5Encode([]byte(strconv.Itoa(fullBgIndex)))[0:10]
- imgGrp := s.md5Encode([]byte(strconv.Itoa(imgGrpIndex)))[10:20]
- var answerDecode []byte
- for i := 0; i < 9; i++ {
- if i%2 == 0 {
- answerDecode = append(answerDecode, fullBg[i])
- } else if i%2 == 1 {
- answerDecode = append(answerDecode, imgGrp[i])
- }
- }
- xDecode := answerDecode[4:]
- xInt64, err := strconv.ParseInt(string(xDecode), 16, 32)
- if err != nil {
- log.Error("%+v", err)
- }
- xInt := int(xInt64)
- result := xInt % 200
- if result < 40 {
- result = 40
- }
- return math.Abs(float64(ans-result)) < thread
- }
|