123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- package common
- import (
- "crypto/hmac"
- "crypto/md5"
- "crypto/sha256"
- "designs/config"
- "designs/global"
- "encoding/hex"
- "encoding/json"
- "errors"
- "fmt"
- "math/rand"
- "net/http"
- "net/url"
- "sort"
- "strconv"
- "strings"
- "time"
- "github.com/gin-gonic/gin"
- "github.com/golang-jwt/jwt/v5"
- )
- // 打印
- func Print(i interface{}) {
- fmt.Println("---")
- fmt.Println(i)
- fmt.Println("---")
- }
- // 返回JSON
- func RetJson(code int, msg string, data interface{}, c *gin.Context) {
- c.JSON(http.StatusOK, gin.H{
- "code": code,
- "msg": msg,
- "data": data,
- "timestamp": GetTimeUnix(),
- })
- c.Abort()
- }
- // 获取当前时间戳
- func GetTimeUnix() int64 {
- return time.Now().Unix()
- }
- // MD5 方法
- func MD5(str string) string {
- s := md5.New()
- s.Write([]byte(str))
- return hex.EncodeToString(s.Sum(nil))
- }
- // 生成签名
- func CreateSign(params url.Values) string {
- var key []string
- var str = ""
- for k := range params {
- if k != "sn" {
- key = append(key, k)
- }
- }
- sort.Strings(key)
- for i := 0; i < len(key); i++ {
- if i == 0 {
- str = fmt.Sprintf("%v=%v", key[i], params.Get(key[i]))
- } else {
- str = str + fmt.Sprintf("&%v=%v", key[i], params.Get(key[i]))
- }
- }
- // 自定义签名算法
- sign := MD5(MD5(str) + MD5(config.Get("app_name")+config.Get("app_secret")))
- return sign
- }
- // 验证签名
- func VerifySign(c *gin.Context) {
- var method = c.Request.Method
- var ts int64
- var sn string
- var req url.Values
- if method == "GET" {
- req = c.Request.URL.Query()
- sn = c.Query("sn")
- ts, _ = strconv.ParseInt(c.Query("ts"), 10, 64)
- } else if method == "POST" {
- c.Request.ParseForm()
- req = c.Request.PostForm
- sn = c.PostForm("sn")
- ts, _ = strconv.ParseInt(c.PostForm("ts"), 10, 64)
- } else {
- RetJson(500, "Illegal requests", "", c)
- return
- }
- exp, _ := strconv.ParseInt(config.Get("api_expire"), 10, 64)
- // 验证过期时间
- if ts > GetTimeUnix() || GetTimeUnix()-ts >= exp {
- RetJson(500, "Ts Error", "", c)
- return
- }
- // 验证签名
- if sn == "" || sn != CreateSign(req) {
- RetJson(500, "Sn Error", "", c)
- return
- }
- }
- func StructToArr(data interface{}) (string, error) {
- res, err := json.Marshal(data)
- if err != nil {
- return "", err
- }
- //将json解析为map
- var mapdata map[string]interface{}
- err1 := json.Unmarshal([]byte(res), &mapdata)
- if err1 != nil {
- return "", err1
- }
- //获取排序map键值
- keys := make([]string, 0, len(mapdata))
- for key := range mapdata {
- keys = append(keys, key)
- }
- //排序
- sort.Strings(keys)
- fmt.Println("我的数据:", string(res))
- //排序后直接构建map
- sortMap := make(map[string]interface{}, len(mapdata))
- for _, key := range keys {
- sortMap[key] = mapdata[key]
- }
- //序列化
- sortJosn, err2 := json.Marshal(sortMap)
- if err2 != nil {
- return "", err2
- }
- return string(sortJosn), nil
- }
- /* 检测数据是否篡改 */
- func VerifySignData(data interface{}) bool {
- var checkSign string
- var sign string = "test"
- checkKey := "secret"
- res, err := json.Marshal(data)
- if err != nil {
- return false
- }
- //将json解析为map
- var mapdata map[string]interface{}
- err1 := json.Unmarshal([]byte(res), &mapdata)
- if err1 != nil {
- return false
- }
- //fmt.Println("解析后的数据:", mapdata)
- val, exist := mapdata[checkKey].(string)
- if exist {
- checkSign = val
- } else {
- return false
- }
- fmt.Println("解析后的数据:", mapdata)
- //获取排序map键值
- keys := make([]string, 0, len(mapdata))
- for key := range mapdata {
- if key != checkKey {
- keys = append(keys, key)
- }
- }
- // fmt.Println("解析后的keys数据:", keys)
- //排序
- sort.Strings(keys)
- //排序后直接构建map
- sortMap := make(map[string]interface{}, len(mapdata))
- for _, key := range keys {
- newKey := strings.ToLower(string(key[0])) + key[1:]
- sortMap[newKey] = mapdata[key]
- }
- //序列化数据
- sortJosn, err2 := json.Marshal(sortMap)
- if err2 != nil {
- return false
- }
- // fmt.Println("我的排序数据:", string(sortJosn), sign)
- // sum := ([]byte("hello world"))
- // fmt.Printf("加密数据:%x\n", sum)
- // 密钥
- key := []byte(config.Get("app.app_check_secret"))
- // 数据
- // data := []byte(msg)
- // 创建一个新的HMAC将SHA-256用作哈希函数
- h := hmac.New(sha256.New, key)
- // 写入数据
- h.Write(sortJosn)
- // 得到MAC
- mac := h.Sum(nil)
- sign = hex.EncodeToString(mac)
- // 打印MAC
- fmt.Println("生成的签名:", sign, checkSign)
- if sign != checkSign {
- global.App.Log.Error("mapdata:", mapdata)
- global.App.Log.Error("sign:", sign)
- global.App.Log.Error("checkSign:", checkSign)
- }
- return sign == checkSign
- }
- // 生成token
- func GetDefineToken(openid string) string {
- timestamp := time.Now().UnixNano() / int64(time.Millisecond)
- randNum := 10000 + rand.Intn(10000)
- token := fmt.Sprintf("%s%d%d", openid, timestamp, randNum)
- return MD5(token)
- }
- // 自定义结构体
- type MyCustomClaims struct {
- UserName string `json:"userName"`
- TokenType int `json:"tokenType"` //0 token 登录 1:刷新token
- jwt.RegisteredClaims
- }
- // 生成jwt token
- func GetJwtToken(UserName string, tokenType int) (string, error) {
- mySigningKey := []byte(config.Get("app.JwtSecret"))
- timeData := time.Second
- if tokenType == 0 {
- timeData = time.Duration(config.GetInt("app.api_exp")) * time.Second
- } else {
- timeData = 24 * time.Hour
- }
- claims := MyCustomClaims{
- UserName,
- tokenType,
- jwt.RegisteredClaims{
- // A usual scenario is to set the expiration time relative to the current time
- ExpiresAt: jwt.NewNumericDate(time.Now().Add(timeData)),
- IssuedAt: jwt.NewNumericDate(time.Now()),
- NotBefore: jwt.NewNumericDate(time.Now()),
- Issuer: "test",
- Subject: "somebody",
- ID: "1",
- Audience: []string{"somebody_else"},
- },
- }
- token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
- ss, err := token.SignedString(mySigningKey)
- return ss, err
- }
- /* 解析jwt */
- func ParseJwtWithClaims(tokenString string) (string, int) {
- token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
- return []byte(config.Get("app.JwtSecret")), nil
- })
- if err != nil {
- // fmt.Println(err)
- return "", 0
- } else if claims, ok := token.Claims.(*MyCustomClaims); ok {
- // fmt.Println(claims.OpenId, claims.RegisteredClaims.Issuer)
- return claims.UserName, claims.TokenType
- } else {
- // fmt.Println("unknown claims type, cannot proceed")
- return "", 0
- }
- }
- // 刷新Token
- func RefreshToken(oldToken string) (string, error) {
- token, err := jwt.Parse(oldToken, func(*jwt.Token) (interface{}, error) {
- return config.Get("app.JwtSecret"), nil
- })
- if err != nil {
- return "", err
- }
- if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
- claims["exp"] = time.Now().Add(time.Duration(config.GetInt("app.api_exp")) * time.Second).Unix() // 更新过期时间
- return jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(config.Get("app.JwtSecret"))
- }
- return "", err
- }
- // 返回剩余时间
- func GetRemainderTime(timeType int) (time.Duration, error) {
- var remaining time.Duration
- err := errors.New("发生错误")
- //获取当前时间
- now := time.Now()
- switch timeType {
- case 2:
- //计算本日剩余时间
- endOfDay := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location())
- remaining = endOfDay.Sub(now)
- case 3:
- //计算本周剩余时间
- daysUntiEndOfWeek := 6 - now.Weekday()
- endOfWeek := time.Date(now.Year(), now.Month(), now.Day()+int(daysUntiEndOfWeek), 23, 59, 59, 0, now.Location())
- remaining = endOfWeek.Sub(now)
- case 4:
- //计算本月剩余时间
- // endOfMonth := time.Date(now.Year(), now.Month()+1, 1, 0, 0, 0, 0, now.Location()).Add(-time.Second)
- // remaining = endOfMonth.Sub(now)
- nextMonth := now.AddDate(0, 1, 0)
- endOfMonth := time.Date(nextMonth.Year(), nextMonth.Month(), 1, 0, 0, 0, 0, nextMonth.Location()).Add(-time.Second)
- remaining = endOfMonth.Sub(now)
- default:
- return remaining, err
- }
- // fmt.Printf("Remaning day data:%v\n", remaining)
- // fmt.Printf("Remaning week data:%v\n", remaining)
- // fmt.Printf("Remaning month data:%v\n", remaining)
- return remaining, nil
- }
|