trade.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package trade
  2. import (
  3. "errors"
  4. "mtp20access/client"
  5. "mtp20access/global"
  6. "mtp20access/model/common/response"
  7. "mtp20access/utils"
  8. "net/http"
  9. "github.com/gin-gonic/gin"
  10. "github.com/gorilla/websocket"
  11. "go.uber.org/zap"
  12. )
  13. // TradeConn 终端连接WebSocket
  14. func TradeConn(c *gin.Context) (err error) {
  15. // 获取请求账号信息
  16. // s, exists := c.Get("claims")
  17. // if !exists {
  18. // err = errors.New("获取请求账号信息异常")
  19. // global.M2A_LOG.Error(err.Error())
  20. // return
  21. // }
  22. // claims := s.(*commonRequest.CustomClaims)
  23. // 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localStorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
  24. token := c.Request.Header.Get("Sec-WebSocket-Protocol")
  25. if token == "" {
  26. response.FailWithDetailed(gin.H{"reload": true}, "未登录或非法访问", c)
  27. c.Abort()
  28. return
  29. }
  30. j := utils.NewJWT()
  31. // parseToken 解析token包含的信息
  32. claims, err := j.ParseToken(token)
  33. if err != nil {
  34. if err == utils.ErrTokenExpired {
  35. response.FailWithCodeAndDetail(gin.H{"reload": true}, response.ERROR_TOKEN_EXPIRED, "授权已过期", c)
  36. // c.Abort()
  37. return
  38. }
  39. response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c)
  40. // c.Abort()
  41. return
  42. }
  43. // 从Redis获取登录信息
  44. loginMap, err := j.GetRedisLogin(claims.LoginID, claims.Group)
  45. if err != nil {
  46. response.FailWithCodeAndDetail(gin.H{"reload": true}, response.ERROR_TOKEN_OTHER_LOGIN, "您的帐户异地登陆或令牌失效", c)
  47. // c.Abort()
  48. return
  49. }
  50. // 判断Token是否有效
  51. if redisToken, isHas := loginMap["token"]; isHas {
  52. if redisToken != token {
  53. response.FailWithCodeAndDetail(gin.H{"reload": true}, response.ERROR_TOKEN_OTHER_LOGIN, "您的帐户异地登陆或令牌失效", c)
  54. // c.Abort()
  55. return
  56. }
  57. } else {
  58. response.FailWithDetailed(gin.H{"reload": true}, "未登录或非法访问", c)
  59. // c.Abort()
  60. return
  61. }
  62. // 获取登录账户信息
  63. client, exists := client.Clients[claims.SessionID]
  64. if !exists {
  65. err = errors.New("获取登录账户信息异常")
  66. global.M2A_LOG.Error(err.Error(), zap.Any("SessionID", claims.SessionID))
  67. return
  68. }
  69. // 需要注意的是,如果前端通过websocket连接时指定了Sec-WebSocket-Protocol,后端接收到连接后,必须原封不动的将Sec-WebSocket-Protocol头信息返回给前端,否则连接会抛出异常。
  70. // c.Header("Sec-WebSocket-Protocol", token)
  71. // c.String(200, "ok")
  72. // 将http连接升级为websocket连接
  73. upGrader := websocket.Upgrader{
  74. ReadBufferSize: 1000000,
  75. WriteBufferSize: 1000000,
  76. CheckOrigin: func(r *http.Request) bool {
  77. return true
  78. },
  79. //将获取的参数放进这个数组
  80. Subprotocols: []string{token},
  81. }
  82. ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
  83. if err != nil {
  84. err = errors.New("连接错误")
  85. global.M2A_LOG.Error("将http连接升级为websocket连接失败", zap.Any("err", err))
  86. return
  87. }
  88. client.SetTradeWebSocket(ws)
  89. return
  90. }