index.go 6.74 KB
package sign

import (
	"apigame/configs/confapi"
	"apigame/middleware/sdk"
	"apigame/service/code-msg"
	"apigame/util/util-lx/lxalilog"
	"apigame/util/util-lx/lxarray"
	"apigame/util/util-lx/lxconv"
	"apigame/util/util-lx/lxlimit"
	"apigame/util/util-lx/lxtime"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"

	"sort"
	"strings"
	"unicode/utf8"

	"github.com/astaxie/beego/validation"
)

type MCheckConfig struct {
	CheckUrlGameID bool
	CheckToken     bool
	CheckSign      bool
	FunName        string
	Bodys          []byte
	Ip             lxlimit.MFuncItem `json:"ip"`
	Kernel         lxlimit.MFuncItem `json:"kernel"`
	Member         lxlimit.MFuncItem `json:"member"`
	Url            string            `json:"url"`
	Params         map[string]string `json:"params"`
}

func getTimeStamp(time_stamp interface{}) (timestamp int64) {
	if time_stamp == nil {
		return
	}

	tsp := ""

	switch tp := time_stamp.(type) {
	case string:
		tsp = fmt.Sprintf("%s", tp)
	}

	if tsp == "" {
		return
	}

	timestamp = lxconv.ParseInt64(tsp)
	lth := utf8.RuneCountInString(tsp)
	if lth > 10 {
		timestamp = timestamp / 1000
	}

	return

}

func InitCheck(postdata interface{}, cgg MCheckConfig) (code string, gameconfig *confapi.ApiGameConfig, err error) {

	var (
		postGameId string
		urlGameId  string
		ty         string
		c          lxlimit.MFuncConfig
		nowtime    = lxtime.NowUninx()
		time_stamp int64
		JG         = int64(2)
	)

	// 检查时间戳
	tempData := make(map[string]interface{})
	_ = json.Unmarshal(cgg.Bodys, &tempData)

	time_stamp = getTimeStamp(tempData["time_stamp"])
	if time_stamp < (nowtime-JG) || time_stamp > (nowtime+JG) {
		code = code_msg.RECODE_REQUESTTIME_ERROR
		err = errors.New(code)
		lxalilog.Errors("RECODE_REQUESTTIME_ERROR error:", string(cgg.Bodys))
		return
	}

	c.Ip = cgg.Ip
	c.Kernel = cgg.Kernel
	c.Params = cgg.Params
	c.Url = cgg.Url
	c.BodyBy = cgg.Bodys
	if cgg.FunName == "" {
		c.FunName = c.Url
	}
	c.Member = cgg.Member

	for k, v := range c.Params {
		if k == ":gameid" {
			urlGameId = v
		}
	}

	if cgg.CheckUrlGameID && urlGameId == "" {
		code = code_msg.RECODE_PARAMERROR
		err = errors.New(code)
		lxalilog.Errors("urlGameid error:")
		return
	}

	postGameId, ty = lxlimit.CheckLimit(c)

	if cgg.CheckUrlGameID && postGameId != urlGameId {
		code = code_msg.RECODE_PARAMERROR
		err = errors.New(code)
		lxalilog.Errors("urlGameid !=postGameId:", urlGameId, postdata)
		return
	}

	if ty != "" {
		code = code_msg.RECODE_REQUESTXIANLIU_ERROR
		err = errors.New(ty)
		return
	}

	err = json.Unmarshal(cgg.Bodys, &postdata)
	if err != nil {
		code = code_msg.RECODE_PARAMERROR
		lxalilog.Errors("json.Unmarshal error:", err, string(cgg.Bodys))
		return
	}

	valid := validation.Validation{}

	var b bool

	b, err = valid.Valid(postdata)
	if err != nil {
		code = code_msg.RECODE_PARAMERROR
		lxalilog.Errors("valid.Valid error:", err, string(cgg.Bodys), valid.Errors)
		return
	}

	if !b {
		code = code_msg.RECODE_PARAMERROR
		err = errors.New(code)
		lxalilog.Errors("valid.Valid error:", err, string(cgg.Bodys), valid.Errors)
		return
	}

	if cgg.CheckSign {
		code, gameconfig, err = CheckSign(postdata, cgg.CheckToken)
		if err != nil {
			return
		}
	}

	return
}

// Check 检查签名
func Check(req []byte, postdata interface{}, checkSign bool, checkToken bool) (code string, err error) {

	err = json.Unmarshal(req, &postdata)
	if err != nil {
		code = code_msg.RECODE_PARAMERROR
		lxalilog.Errors("json.Unmarshal error:", err, string(req))
		return
	}

	valid := validation.Validation{}

	var b bool

	fmt.Println(postdata)
	fmt.Println(reflect.TypeOf(postdata))
	fmt.Println(reflect.TypeOf(postdata).Kind())

	b, err = valid.Valid(postdata)
	if err != nil {
		code = code_msg.RECODE_PARAMERROR
		lxalilog.Errors("valid.Valid error:", err, string(req), valid.Errors)
		return
	}

	if !b {
		code = code_msg.RECODE_PARAMERROR
		err = errors.New(code)
		lxalilog.Errors("valid.Valid error:", err, string(req), valid.Errors)
		return
	}

	if checkSign {
		code, _, err = CheckSign(postdata, checkToken)
		if err != nil {
			return
		}
	}

	return
}

// CheckSign 校验签名
func CheckSign(data interface{}, checkToken bool) (code string, gameconfig *confapi.ApiGameConfig, err error) {

	var (
		logstr string
	)

	jsonBody, _ := json.Marshal(data)

	logstr += string(jsonBody)

	var newdata = make(map[string]interface{})

	err = json.Unmarshal(jsonBody, &newdata)
	if err != nil {
		code = code_msg.RECODE_SIGNERROR
		lxalilog.Errors("json.Unmarshal error:", err)
		return
	}

	if newdata["gameid"] == "" || newdata["channel"] == "" || newdata["sign"] == "" || newdata["sign_type"] == "" || newdata["time_stamp"] == "" || newdata["ver"] == "" {
		code = code_msg.RECODE_SIGNERROR
		err = errors.New("签名错误,参数错误" + logstr)
		lxalilog.Errors(err)
		return
	}

	gameid := newdata["gameid"].(string)

	gameconfig, err = confapi.GetConfig(gameid)
	if err != nil {
		lxalilog.Errors(err)
		return
	}

	if newdata["sign"].(string) == "fb0ba80fad895664c7aea7c8ce462505" {
		return
	}

	appkey := gameconfig.AppKey

	if appkey == "" {
		code = code_msg.RECODE_SIGNERROR
		err = errors.New("签名错误,参数错误" + gameid + "no appkey")
		lxalilog.Errors(err)
		return
	}

	sign := newdata["sign"]

	sortdata := make([]string, 0, len(newdata))

	fiterword := "and|exec|insert|select|delete|update|count|master|truncate|declare|char(|mid(|chr(|'"
	fiterwords := strings.Split(fiterword, "|")
	var fiterkey []interface{}

	for k, v := range newdata {
		newv := lxconv.InterfaceToStr(v)

		if b := lxarray.InArray(newv, fiterwords); b {
			fiterkey = append(fiterkey, k)
		}
		if newv != "" && newv != "0" && k != "sign" && k != "ver" && k != "dev" && k != "dever" && k != "pkv" {
			sortdata = append(sortdata, k)
		}
	}

	if len(fiterkey) > 0 {
		code = code_msg.RECODE_WEIXINAZIFU_ERROR
		err = errors.New("fiterkey error" + logstr)
		lxalilog.Errors(err, lxconv.JsonEncode(fiterkey), "data:", lxconv.JsonEncode(newdata))
		return
	}

	sort.Strings(sortdata)
	valstr := ""
	for _, k := range sortdata { // 先下标,再数值
		v := lxconv.InterfaceToStr(newdata[k])
		valstr += k + "=" + v
	}

	valstr += appkey

	logstr += ",valstr:(" + valstr + ")"

	md5key := strings.ToLower(lxconv.EncryMD5(valstr))

	if md5key != sign {
		code = code_msg.RECODE_SIGNERROR
		err = errors.New(code)
		lxalilog.Errors("sign error,md5key::", md5key, ",sign:", sign, logstr, "data:", lxconv.JsonEncode(newdata))
		return
	}

	if checkToken {

		if newdata["uid"] == nil || newdata["token"] == nil {
			code = code_msg.RECODE_PARAMERROR
			err = errors.New(code)
			lxalilog.Errors("no uid or token", "data:", lxconv.JsonEncode(newdata))
			return
		}

		err = sdk.CheckSdkToken(gameid, lxconv.ToInt64(newdata["uid"]), lxconv.InterfaceToStr(newdata["token"]))
		if err != nil {
			code = code_msg.RECODE_LOGINCHECK_ERROR
			return
		}

	}

	return
}