package token import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "errors" "fmt" "mtp2_if/config" "mtp2_if/global/e" "mtp2_if/rediscli" "net/http" "runtime" "strconv" "strings" "time" "github.com/gin-gonic/gin" ) // TouristToken 游客Token var TouristToken string = "c886a057f3d820d4dbc41473686c7c2d" // CheckToken Token校验 func CheckToken(loginid string, token string, group string) (string, error) { key := "" if len(group) == 0 { key = fmt.Sprintf("monitor:online_loginid::%s", loginid) } else { key = fmt.Sprintf("monitor:online_loginid:%s:%s", loginid, group) } field := "Token" realToken, err := rediscli.GetRedisClient().HGet(key, field).Result() if err != nil { return "", err } if realToken != token { return "", errors.New("token is invalid") } // 获取UserID userID, err := rediscli.GetRedisClient().HGet(key, "UserID").Result() return userID, err } // Auth Token校验中间件 func Auth() gin.HandlerFunc { return func(c *gin.Context) { // if config.SerCfg.GetDebugMode() { // c.Next() // return // } // windows下方便开发调试, 不做token校验 if config.SerCfg.GetDebugMode() && runtime.GOOS == "windows" { c.Next() return } var code int var data interface{} userID := "" code = e.SUCCESS token := c.GetHeader("Authorization") if token == "" { // Token缺失 code = e.ERROR_AUTH_CHECK_TOKEN_FAIL } else { // 获取loginid s := strings.Split(token, "_") loginid := s[0] // 支持分组功能 group := "" if len(s) == 3 { group = s[2] } var err error userID, err = CheckToken(loginid, token, group) if err != nil { // Token错误 code = e.ERROR_AUTH_CHECK_TOKEN_FAIL } } // Token检验失败 if code != e.SUCCESS { c.JSON(http.StatusUnauthorized, gin.H{ "code": code, "msg": e.GetMsg(code), "data": data, }) c.Abort() return } // FIXME: - 针对POST接口,应判断传入TOKEN对应的用户是否正确(比如判断UserID或AccountID是否对得上等),后期处理 if c.Request.Method == "POST" { c.Set("requserid", userID) } if config.SerCfg.GetApiKeyMode() { timestamp := c.GetHeader("Timestamp") verification := c.GetHeader("Verification") if timestamp == "" || token == "" || verification == "" { c.JSON(http.StatusUnauthorized, gin.H{ "code": e.ERROR, "msg": "apikey1", "data": struct{}{}, }) c.Abort() return } // 判断时间,10S之内有效 t, err := strconv.Atoi(timestamp) if err != nil { c.JSON(http.StatusUnauthorized, gin.H{ "code": e.ERROR, "msg": "apikey2", "data": struct{}{}, }) c.Abort() return } if time.Now().UnixMilli()-int64(t) > 10*1000 { c.JSON(http.StatusUnauthorized, gin.H{ "code": e.ERROR, "msg": "apikey3", "data": struct{}{}, }) c.Abort() return } s := fmt.Sprintf("%s%s", token, timestamp) hashed := hmac.New(sha256.New, []byte(config.SerCfg.WebCfg.ApiKey)) hashed.Write([]byte(s)) h := hex.EncodeToString(hashed.Sum(nil)) if h == "" { c.JSON(http.StatusUnauthorized, gin.H{ "code": e.ERROR, "msg": "apikey4", "data": struct{}{}, }) c.Abort() return } if h != verification { c.JSON(http.StatusUnauthorized, gin.H{ "code": e.ERROR, "msg": "apikey5", "data": struct{}{}, }) c.Abort() return } } // Token检验成功 c.Next() } } // AuthByHsby 游客鉴权 func AuthByHsby() gin.HandlerFunc { return func(c *gin.Context) { // 包含accountID、accountIDs、userID和userIDs等参数需要走正常鉴权 accountID := c.Query("accountID") accountIDs := c.Query("accountIDs") userID := c.Query("userID") userIDs := c.Query("userIDs") loginID := c.Query("loginID") if len(accountID) != 0 || len(accountIDs) != 0 || len(userID) != 0 || len(userIDs) != 0 || len(loginID) != 0 { realToken(c) return } var code int var data interface{} code = e.SUCCESS token := c.GetHeader("Authorization") if token == "" { // Token缺失 code = e.ERROR_AUTH_CHECK_TOKEN_FAIL } else { // Token带下划线的走正常鉴权 if strings.Contains(token, "_") { realToken(c) return } if token != TouristToken { // Token错误 code = e.ERROR_AUTH_CHECK_TOKEN_FAIL } } // Token检验失败 if code != e.SUCCESS { c.JSON(http.StatusUnauthorized, gin.H{ "code": code, "msg": e.GetMsg(code), "data": data, }) c.Abort() return } // Token检验成功 c.Next() } } func realToken(c *gin.Context) { // if config.SerCfg.GetDebugMode() { // c.Next() // return // } var code int var data interface{} code = e.SUCCESS token := c.GetHeader("Authorization") if token == "" { // Token缺失 code = e.ERROR_AUTH_CHECK_TOKEN_FAIL } else { // 获取loginid s := strings.Split(token, "_") loginid := s[0] // 支持分组功能 group := "" if len(s) == 3 { group = s[2] } if _, err := CheckToken(loginid, token, group); err != nil { // Token错误 code = e.ERROR_AUTH_CHECK_TOKEN_FAIL } } // Token检验失败 if code != e.SUCCESS { c.JSON(http.StatusUnauthorized, gin.H{ "code": code, "msg": e.GetMsg(code), "data": data, }) c.Abort() return } // FIXME: - 针对POST接口,应判断传入TOKEN对应的用户是否正确(比如判断UserID或AccountID是否对得上等),后期处理 // Token检验成功 c.Next() return }