common.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. package common
  2. import (
  3. "crypto/hmac"
  4. "crypto/md5"
  5. "crypto/sha256"
  6. "designs/config"
  7. "designs/global"
  8. "encoding/hex"
  9. "encoding/json"
  10. "errors"
  11. "fmt"
  12. "math/rand"
  13. "net/http"
  14. "net/url"
  15. "sort"
  16. "strconv"
  17. "strings"
  18. "time"
  19. "github.com/gin-gonic/gin"
  20. "github.com/golang-jwt/jwt/v5"
  21. )
  22. // 打印
  23. func Print(i interface{}) {
  24. fmt.Println("---")
  25. fmt.Println(i)
  26. fmt.Println("---")
  27. }
  28. // 返回JSON
  29. func RetJson(code int, msg string, data interface{}, c *gin.Context) {
  30. c.JSON(http.StatusOK, gin.H{
  31. "code": code,
  32. "msg": msg,
  33. "data": data,
  34. "timestamp": GetTimeUnix(),
  35. })
  36. c.Abort()
  37. }
  38. // 获取当前时间戳
  39. func GetTimeUnix() int64 {
  40. return time.Now().Unix()
  41. }
  42. // MD5 方法
  43. func MD5(str string) string {
  44. s := md5.New()
  45. s.Write([]byte(str))
  46. return hex.EncodeToString(s.Sum(nil))
  47. }
  48. // 生成签名
  49. func CreateSign(params url.Values) string {
  50. var key []string
  51. var str = ""
  52. for k := range params {
  53. if k != "sn" {
  54. key = append(key, k)
  55. }
  56. }
  57. sort.Strings(key)
  58. for i := 0; i < len(key); i++ {
  59. if i == 0 {
  60. str = fmt.Sprintf("%v=%v", key[i], params.Get(key[i]))
  61. } else {
  62. str = str + fmt.Sprintf("&%v=%v", key[i], params.Get(key[i]))
  63. }
  64. }
  65. // 自定义签名算法
  66. sign := MD5(MD5(str) + MD5(config.Get("app_name")+config.Get("app_secret")))
  67. return sign
  68. }
  69. // 验证签名
  70. func VerifySign(c *gin.Context) {
  71. var method = c.Request.Method
  72. var ts int64
  73. var sn string
  74. var req url.Values
  75. if method == "GET" {
  76. req = c.Request.URL.Query()
  77. sn = c.Query("sn")
  78. ts, _ = strconv.ParseInt(c.Query("ts"), 10, 64)
  79. } else if method == "POST" {
  80. c.Request.ParseForm()
  81. req = c.Request.PostForm
  82. sn = c.PostForm("sn")
  83. ts, _ = strconv.ParseInt(c.PostForm("ts"), 10, 64)
  84. } else {
  85. RetJson(500, "Illegal requests", "", c)
  86. return
  87. }
  88. exp, _ := strconv.ParseInt(config.Get("api_expire"), 10, 64)
  89. // 验证过期时间
  90. if ts > GetTimeUnix() || GetTimeUnix()-ts >= exp {
  91. RetJson(500, "Ts Error", "", c)
  92. return
  93. }
  94. // 验证签名
  95. if sn == "" || sn != CreateSign(req) {
  96. RetJson(500, "Sn Error", "", c)
  97. return
  98. }
  99. }
  100. func StructToArr(data interface{}) (string, error) {
  101. res, err := json.Marshal(data)
  102. if err != nil {
  103. return "", err
  104. }
  105. //将json解析为map
  106. var mapdata map[string]interface{}
  107. err1 := json.Unmarshal([]byte(res), &mapdata)
  108. if err1 != nil {
  109. return "", err1
  110. }
  111. //获取排序map键值
  112. keys := make([]string, 0, len(mapdata))
  113. for key := range mapdata {
  114. keys = append(keys, key)
  115. }
  116. //排序
  117. sort.Strings(keys)
  118. fmt.Println("我的数据:", string(res))
  119. //排序后直接构建map
  120. sortMap := make(map[string]interface{}, len(mapdata))
  121. for _, key := range keys {
  122. sortMap[key] = mapdata[key]
  123. }
  124. //序列化
  125. sortJosn, err2 := json.Marshal(sortMap)
  126. if err2 != nil {
  127. return "", err2
  128. }
  129. return string(sortJosn), nil
  130. }
  131. /* 检测数据是否篡改 */
  132. func VerifySignData(data interface{}) bool {
  133. var checkSign string
  134. var sign string = "test"
  135. checkKey := "secret"
  136. res, err := json.Marshal(data)
  137. if err != nil {
  138. return false
  139. }
  140. //将json解析为map
  141. var mapdata map[string]interface{}
  142. err1 := json.Unmarshal([]byte(res), &mapdata)
  143. if err1 != nil {
  144. return false
  145. }
  146. //fmt.Println("解析后的数据:", mapdata)
  147. val, exist := mapdata[checkKey].(string)
  148. if exist {
  149. checkSign = val
  150. } else {
  151. return false
  152. }
  153. fmt.Println("解析后的数据:", mapdata)
  154. //获取排序map键值
  155. keys := make([]string, 0, len(mapdata))
  156. for key := range mapdata {
  157. if key != checkKey {
  158. keys = append(keys, key)
  159. }
  160. }
  161. // fmt.Println("解析后的keys数据:", keys)
  162. //排序
  163. sort.Strings(keys)
  164. //排序后直接构建map
  165. sortMap := make(map[string]interface{}, len(mapdata))
  166. for _, key := range keys {
  167. newKey := strings.ToLower(string(key[0])) + key[1:]
  168. sortMap[newKey] = mapdata[key]
  169. }
  170. //序列化数据
  171. sortJosn, err2 := json.Marshal(sortMap)
  172. if err2 != nil {
  173. return false
  174. }
  175. // fmt.Println("我的排序数据:", string(sortJosn), sign)
  176. // sum := ([]byte("hello world"))
  177. // fmt.Printf("加密数据:%x\n", sum)
  178. // 密钥
  179. key := []byte(config.Get("app.app_check_secret"))
  180. // 数据
  181. // data := []byte(msg)
  182. // 创建一个新的HMAC将SHA-256用作哈希函数
  183. h := hmac.New(sha256.New, key)
  184. // 写入数据
  185. h.Write(sortJosn)
  186. // 得到MAC
  187. mac := h.Sum(nil)
  188. sign = hex.EncodeToString(mac)
  189. // 打印MAC
  190. fmt.Println("生成的签名:", sign, checkSign)
  191. if sign != checkSign {
  192. global.App.Log.Error("mapdata:", mapdata)
  193. global.App.Log.Error("sign:", sign)
  194. global.App.Log.Error("checkSign:", checkSign)
  195. }
  196. return sign == checkSign
  197. }
  198. // 生成token
  199. func GetDefineToken(openid string) string {
  200. timestamp := time.Now().UnixNano() / int64(time.Millisecond)
  201. randNum := 10000 + rand.Intn(10000)
  202. token := fmt.Sprintf("%s%d%d", openid, timestamp, randNum)
  203. return MD5(token)
  204. }
  205. // 自定义结构体
  206. type MyCustomClaims struct {
  207. OpenId string `json:"openid"`
  208. Gid string `json:"gid"`
  209. Pf string `json:"pf"`
  210. TokenType int `json:"tokenType"` //0 token 登录 1:刷新token
  211. jwt.RegisteredClaims
  212. }
  213. // 生成jwt token
  214. func GetJwtToken(openId string, gid string, pf string, tokenType int) (string, error) {
  215. mySigningKey := []byte(config.Get("app.JwtSecret"))
  216. timeData := time.Second
  217. if tokenType == 0 {
  218. timeData = time.Duration(config.GetInt("app.api_exp")) * time.Second
  219. } else {
  220. timeData = 24 * time.Hour
  221. }
  222. claims := MyCustomClaims{
  223. openId,
  224. gid,
  225. pf,
  226. tokenType,
  227. jwt.RegisteredClaims{
  228. // A usual scenario is to set the expiration time relative to the current time
  229. ExpiresAt: jwt.NewNumericDate(time.Now().Add(timeData)),
  230. IssuedAt: jwt.NewNumericDate(time.Now()),
  231. NotBefore: jwt.NewNumericDate(time.Now()),
  232. Issuer: "test",
  233. Subject: "somebody",
  234. ID: "1",
  235. Audience: []string{"somebody_else"},
  236. },
  237. }
  238. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  239. ss, err := token.SignedString(mySigningKey)
  240. return ss, err
  241. }
  242. /* 解析jwt */
  243. func ParseJwtWithClaims(tokenString string) (string, string, string, int) {
  244. token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
  245. return []byte(config.Get("app.JwtSecret")), nil
  246. })
  247. if err != nil {
  248. // fmt.Println(err)
  249. return "", "", "", 0
  250. } else if claims, ok := token.Claims.(*MyCustomClaims); ok {
  251. // fmt.Println(claims.OpenId, claims.RegisteredClaims.Issuer)
  252. return claims.OpenId, claims.Gid, claims.Pf, claims.TokenType
  253. } else {
  254. // fmt.Println("unknown claims type, cannot proceed")
  255. return "", "", "", 0
  256. }
  257. }
  258. // 刷新Token
  259. func RefreshToken(oldToken string) (string, error) {
  260. token, err := jwt.Parse(oldToken, func(*jwt.Token) (interface{}, error) {
  261. return config.Get("app.JwtSecret"), nil
  262. })
  263. if err != nil {
  264. return "", err
  265. }
  266. if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
  267. claims["exp"] = time.Now().Add(time.Duration(config.GetInt("app.api_exp")) * time.Second).Unix() // 更新过期时间
  268. return jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(config.Get("app.JwtSecret"))
  269. }
  270. return "", err
  271. }
  272. // 返回剩余时间
  273. func GetRemainderTime(timeType int) (time.Duration, error) {
  274. var remaining time.Duration
  275. err := errors.New("发生错误")
  276. //获取当前时间
  277. now := time.Now()
  278. switch timeType {
  279. case 2:
  280. //计算本日剩余时间
  281. endOfDay := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location())
  282. remaining = endOfDay.Sub(now)
  283. case 3:
  284. //计算本周剩余时间
  285. daysUntiEndOfWeek := 6 - now.Weekday()
  286. endOfWeek := time.Date(now.Year(), now.Month(), now.Day()+int(daysUntiEndOfWeek), 23, 59, 59, 0, now.Location())
  287. remaining = endOfWeek.Sub(now)
  288. case 4:
  289. //计算本月剩余时间
  290. // endOfMonth := time.Date(now.Year(), now.Month()+1, 1, 0, 0, 0, 0, now.Location()).Add(-time.Second)
  291. // remaining = endOfMonth.Sub(now)
  292. nextMonth := now.AddDate(0, 1, 0)
  293. endOfMonth := time.Date(nextMonth.Year(), nextMonth.Month(), 1, 0, 0, 0, 0, nextMonth.Location()).Add(-time.Second)
  294. remaining = endOfMonth.Sub(now)
  295. default:
  296. return remaining, err
  297. }
  298. // fmt.Printf("Remaning day data:%v\n", remaining)
  299. // fmt.Printf("Remaning week data:%v\n", remaining)
  300. // fmt.Printf("Remaning month data:%v\n", remaining)
  301. return remaining, nil
  302. }