package middleware import ( "fmt" "sfbase/global" "sfbase/redis" sutils "sfbase/utils" "sfis/db" "sfis/model" "sfis/model/response" "sfis/utils" "strconv" "strings" "time" "github.com/gin-gonic/gin" "go.uber.org/zap" ) const TimestampExpireTime = 600 //单位秒,header里的时间戳超时时间 10分钟 func TokenAuth() gin.HandlerFunc { return func(context *gin.Context) { var ( requestUrl string token string timestamp string appID string productID int requestIP string ) requestUrl = context.Request.URL.String() global.Logger.Info(requestUrl) requestUrl = strings.Split(requestUrl, "v1")[1] global.Logger.Info(requestUrl) // a := strings.Split(requestUrl, "/") // requestUrl = a[4] if p, ok := utils.ApiUrlCache.Load(requestUrl); ok { productID = p.(int) } else { response.FailWithDetailed(response.ParamError, nil, "url错误", context) context.Abort() return } // productID = 1000 token = context.Request.Header.Get("token") timestamp = context.Request.Header.Get("timestamp") appID = context.PostForm("app_id") if appID == "" || token == "" || timestamp == "" { response.FailWithDetailed(response.ParamEmpty, nil, "参数缺失或为空", context) context.Abort() return } _timestamp, err := strconv.ParseInt(timestamp, 10, 64) if err != nil { response.FailWithDetailed(response.ParamError, nil, "参数异常", context) context.Abort() return } now := time.Now().Unix() TimestampExpire := now - _timestamp if TimestampExpire < 0 { TimestampExpire = -TimestampExpire } if TimestampExpire > TimestampExpireTime { //token时间验证 十分钟 response.FailWithDetailed(response.TokenExpired, nil, "签名过期", context) context.Abort() return } user := utils.GetUserByAppID(appID) secretKey := user.SecretKey ipWhiteList := user.IpWhiteList userName := user.Name global.Logger.Info("用户:", zap.Any("userName:", userName), zap.Any("appID:", appID), zap.Any("secretKey:", secretKey), zap.Any("ipWhiteList:", ipWhiteList)) /** 第一步:ip白名单校验 */ requestIP = utils.GetIp(context.Request) if ipWhiteList != "*" { if strings.Index(ipWhiteList, requestIP) < 0 { response.FailWithDetailed(response.IpInvalid, nil, "ip不在白名单", context) context.Abort() return } } /** 第二步:MD5签名校验 */ signToken := sutils.MD5(fmt.Sprintf("%s%s%s", appID, timestamp, user.SecretKey)) if token != signToken { response.FailWithDetailed(response.TokenInvalid, nil, "身份验证失败", context) context.Abort() return } userProduct := &model.UserProduct{} db.GetSFISDB().First(userProduct, &model.UserProduct{AppID: appID, ProductID: productID}) //校验是否过期 end := userProduct.EndAt if now > end.Unix() { response.FailWithDetailed(response.InterfaceExpired, nil, "剩余量已过期", context) context.Abort() return } //校验每日调用上限 limittodaykey := fmt.Sprintf("limittoday_%d_%d_%s", time.Now().Day(), productID, appID) limittoday := redis.GetInt("limit", limittodaykey) if limittoday >= userProduct.CallTimesLimitDay { //当天调用超过次数 response.FailWithDetailed(response.MoreThanEveryDayDataNumberLimit, nil, "请求超过每日调用总量限制", context) context.Abort() return } else { if limittoday == 0 { _, max := sutils.GetDayMinMax(time.Now()) redis.Put("limit", limittodaykey, 0, int(max-now)) } } context.Set("appID", appID) context.Set("productID", productID) context.Set("requestIP", requestIP) } }