auth.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package middleware
  2. import (
  3. "fmt"
  4. "github.com/gin-gonic/gin"
  5. "go.uber.org/zap"
  6. "sfbase/global"
  7. sutils "sfbase/utils"
  8. "sfis/db"
  9. "sfis/lock"
  10. "sfis/model"
  11. "sfis/model/response"
  12. "sfis/utils"
  13. "strconv"
  14. "strings"
  15. "time"
  16. )
  17. const TimestampExpireTime = 600 //单位秒,header里的时间戳超时时间 10分钟
  18. func TokenAuth() gin.HandlerFunc {
  19. return func(context *gin.Context) {
  20. var (
  21. requestUrl string
  22. token string
  23. timestamp string
  24. appID string
  25. productID int
  26. )
  27. requestUrl = context.Request.URL.String()
  28. requestUrl = strings.Split(requestUrl, "?")[0]
  29. requestUrl = strings.Split(requestUrl, "/")[3]
  30. if p, ok := utils.ApiUrlCache.Load(requestUrl); ok {
  31. productID = p.(*model.Product).ID
  32. } else {
  33. response.FailWithDetailed(response.ParamError, nil, "url错误", context)
  34. context.Abort()
  35. return
  36. }
  37. token = context.Request.Header.Get("token")
  38. timestamp = context.Request.Header.Get("timestamp")
  39. appID = context.PostForm("app_id")
  40. if appID == "" || token == "" || timestamp == "" {
  41. response.FailWithDetailed(response.ParamEmpty, nil, "参数缺失或为空", context)
  42. context.Abort()
  43. return
  44. }
  45. _timestamp, err := strconv.ParseInt(timestamp, 10, 64)
  46. if err != nil {
  47. response.FailWithDetailed(response.ParamError, nil, "参数异常", context)
  48. context.Abort()
  49. return
  50. }
  51. now := time.Now().Unix()
  52. if now-_timestamp > TimestampExpireTime {
  53. //token时间验证 十分钟
  54. response.FailWithDetailed(response.TokenExpired, nil, "签名过期", context)
  55. context.Abort()
  56. return
  57. }
  58. user := utils.GetUserByAppID(appID)
  59. secretKey := user.SecretKey
  60. ipWhiteList := user.IpWhiteList
  61. userName := user.Name
  62. global.Logger.Info("用户:", zap.Any("userName:", userName), zap.Any("appID:", appID), zap.Any("secretKey:", secretKey), zap.Any("ipWhiteList:", ipWhiteList))
  63. /**
  64. 第一步:ip白名单校验
  65. */
  66. if ipWhiteList != "*" {
  67. requestIp := utils.GetIp(context.Request)
  68. if strings.Index(ipWhiteList, requestIp) < 0 {
  69. response.FailWithDetailed(response.IpInvalid, nil, "ip不在白名单", context)
  70. context.Abort()
  71. return
  72. }
  73. }
  74. /**
  75. 第二步:MD5签名校验
  76. */
  77. signToken := sutils.MD5(fmt.Sprintf("%s%s%s", appID, timestamp, user.SecretKey))
  78. if token != signToken {
  79. response.FailWithDetailed(response.TokenInvalid, nil, "身份验证失败", context)
  80. context.Abort()
  81. return
  82. }
  83. context.Set("appID", appID)
  84. context.Set("productID", productID)
  85. if userLock := lock.GetUserLock(appID); userLock != nil {
  86. /**
  87. 第二步:用户接口产品校验-加锁处理
  88. */
  89. //2.1 取用户接口状态校验
  90. userLock.Lock()
  91. userProduct := &model.UserProduct{}
  92. db.GetSFISDB().First(userProduct, &model.UserProduct{AppID: appID, ProductID: productID})
  93. userLock.Unlock()
  94. if userProduct.InterfaceStatus != 0 {
  95. response.FailWithDetailed(response.InterfaceDeleted, nil, "该用户接口已停用", context)
  96. context.Abort()
  97. return
  98. }
  99. //2.2 取用户余量|账户余额 校验
  100. costModel := userProduct.CostModel
  101. product := utils.GetProductByID(productID)
  102. productType := product.ProductType
  103. userLock.Lock()
  104. switch costModel {
  105. case 0:
  106. //按剩余量扣费
  107. if productType == 0 {
  108. //按次扣费-每调一次 剩余量-1
  109. userProduct.LeftNum = userProduct.LeftNum - 1
  110. } else if productType == 1 {
  111. //按条扣费-每调一次剩余量-len(getDataList )
  112. }
  113. case 1:
  114. //按账户钱包余额扣费
  115. if productType == 0 {
  116. //按次扣费-每调一次
  117. //todo 账户余额表user_account的余额 减去 product单价*1
  118. } else if productType == 1 {
  119. //按条扣费-每调一次
  120. //todo 账户余额表user_account的余额 减去 product单价*len(getDataList)
  121. }
  122. case 2:
  123. //优先扣剩余量,剩余量为0,扣钱包余额
  124. }
  125. }
  126. }
  127. }