mw_vaild.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. package utils
  2. import (
  3. "bytes"
  4. "crypto/md5"
  5. "encoding/hex"
  6. "encoding/json"
  7. "github.com/gin-gonic/gin"
  8. "io/ioutil"
  9. "net/http"
  10. "net/url"
  11. "sort"
  12. "strings"
  13. )
  14. /**
  15. Sign的格式如下:
  16. 所有的请求参数加上appkey=lzwg-app-N78ya51qaz2wsx!排序后,再MD5
  17. */
  18. const AppKey string = "lzyd-sign-7c423d19cb2b"
  19. func ValidSign(forceValid bool) gin.HandlerFunc {
  20. return func(c *gin.Context) {
  21. // 暂时不对swagger做强校验
  22. if strings.Contains(c.Request.RequestURI, "swagger") {
  23. c.Next()
  24. return
  25. }
  26. if strings.Contains(c.Request.Header.Get("Referer"), "swagger") {
  27. c.Next()
  28. return
  29. }
  30. if !forceValid {
  31. c.Next()
  32. return
  33. }
  34. validSign(c, AppKey)
  35. }
  36. }
  37. //从Header验证参数
  38. func ValidHeaderParams() gin.HandlerFunc {
  39. return func(c *gin.Context) {
  40. //判断是否合法请求
  41. client := c.Request.Header.Get("client")
  42. guid := c.Request.Header.Get("guid")
  43. timestamp := c.Request.Header.Get("timestamp")
  44. sig := c.Request.Header.Get("sig")
  45. if client == "2" { //wap鉴权
  46. //sig:md5(client+'lz2019_random'+uuid+timestamp)
  47. _sig := Md5Encode(client + "lz2019_random" + guid + timestamp)
  48. if _sig == sig { //鉴权通过
  49. //fmt.Println("_sig == sig")
  50. //c.JSON(http.StatusOK, gin.H{"message": "授权成功"})
  51. c.Next()
  52. } else { //请求非法
  53. //fmt.Println("_sig != sig")
  54. c.Abort()
  55. c.JSON(http.StatusForbidden, gin.H{"message": "访问未授权"})
  56. // return可省略, 只要前面执行Abort()就可以让后面的handler函数不再执行
  57. return
  58. }
  59. } else {
  60. c.Next()
  61. }
  62. }
  63. }
  64. func validSign(c *gin.Context, appKey string) {
  65. var (
  66. inSign string
  67. outSign string
  68. )
  69. if c.Request.Method == "GET" {
  70. values := c.Request.URL.Query()
  71. if len(values) <= 0 {
  72. c.Next()
  73. return
  74. }
  75. inSign = values.Get("sign")
  76. if len(inSign) == 0 {
  77. c.JSON(http.StatusOK, gin.H{
  78. "code": -1,
  79. "message": "未传入签名参数",
  80. })
  81. c.Abort()
  82. return
  83. }
  84. outSign = calculateSignFromValues(values, appKey)
  85. } else {
  86. c.Request.ParseMultipartForm(32 << 20)
  87. formData := c.Request.PostForm
  88. if len(formData) > 0 {
  89. inSign = formData.Get("sign")
  90. if len(inSign) == 0 {
  91. c.JSON(http.StatusOK, gin.H{
  92. "code": -1,
  93. "message": "未传入签名参数",
  94. })
  95. c.Abort()
  96. return
  97. }
  98. outSign = calculateSignFromValues(formData, appKey)
  99. } else {
  100. var params map[string]interface{}
  101. data, _ := c.GetRawData()
  102. err := json.Unmarshal(data, &params)
  103. if err != nil {
  104. panic(err)
  105. }
  106. inSign = Interface2String(params["sign"])
  107. if len(inSign) == 0 {
  108. c.JSON(http.StatusOK, gin.H{
  109. "code": -1,
  110. "message": "未传入签名参数",
  111. })
  112. c.Abort()
  113. return
  114. }
  115. outSign = calculateSignFromJsonBody(params, appKey)
  116. // 很关键,把读过的字节流重新放到body
  117. c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(data))
  118. }
  119. }
  120. if outSign != inSign {
  121. c.JSON(http.StatusOK, gin.H{
  122. "code": -1,
  123. "message": "签名验证错误",
  124. })
  125. c.Abort()
  126. }
  127. c.Next()
  128. }
  129. func calculateSignFromValues(values url.Values, appKey string) string {
  130. values.Del("sign")
  131. values.Add("secret", appKey)
  132. if len(values) > 0 {
  133. // 先对Key进行排序
  134. var keywords []string
  135. for key, _ := range values {
  136. keywords = append(keywords, key)
  137. }
  138. sort.Strings(keywords)
  139. // 再根据Key查找参数Map, 并拼接成字符串
  140. var stringBuffer bytes.Buffer
  141. keywordsCnt := len(keywords)
  142. for i := 0; i < keywordsCnt-1; i++ {
  143. keyword := keywords[i]
  144. stringBuffer.WriteString(keyword + "=" + values.Get(keyword))
  145. stringBuffer.WriteString("&")
  146. }
  147. lastKeyword := keywords[keywordsCnt-1]
  148. stringBuffer.WriteString(lastKeyword + "=" + values.Get(lastKeyword))
  149. // 最后MD5加密
  150. hash := md5.New()
  151. hash.Write(stringBuffer.Bytes())
  152. return hex.EncodeToString(hash.Sum(nil))
  153. }
  154. return ""
  155. }
  156. func calculateSignFromJsonBody(params map[string]interface{}, appKey string) string {
  157. delete(params, "sign")
  158. params["secret"] = appKey
  159. if len(params) > 0 {
  160. // 先对Key进行排序
  161. var keywords []string
  162. for key, _ := range params {
  163. keywords = append(keywords, key)
  164. }
  165. sort.Strings(keywords)
  166. // 再根据Key查找参数Map, 并拼接成字符串
  167. var stringBuffer bytes.Buffer
  168. keywordsCnt := len(keywords)
  169. for i := 0; i < keywordsCnt-1; i++ {
  170. keyword := keywords[i]
  171. stringBuffer.WriteString(keyword + "=" + Interface2String(params[keyword]))
  172. stringBuffer.WriteString("&")
  173. }
  174. lastKeyword := keywords[keywordsCnt-1]
  175. stringBuffer.WriteString(lastKeyword + "=" + Interface2String(params[lastKeyword]))
  176. // 最后MD5加密
  177. hash := md5.New()
  178. hash.Write(stringBuffer.Bytes())
  179. return hex.EncodeToString(hash.Sum(nil))
  180. }
  181. return ""
  182. }