middleware.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. package router
  2. import (
  3. "bytes"
  4. "context"
  5. "errors"
  6. "io"
  7. "net/http"
  8. "time"
  9. "github.com/gin-gonic/gin"
  10. "github.com/go-redis/redis/v8"
  11. jsoniter "github.com/json-iterator/go"
  12. mhayaTime "github.com/mhaya/extend/time"
  13. cfacade "github.com/mhaya/facade"
  14. "github.com/mhaya/game/game_cluster/internal/code"
  15. "github.com/mhaya/game/game_cluster/internal/constant"
  16. "github.com/mhaya/game/game_cluster/internal/mdb"
  17. "github.com/mhaya/game/game_cluster/internal/mdb/eventmodels"
  18. "github.com/mhaya/game/game_cluster/internal/mdb/models"
  19. "github.com/mhaya/game/game_cluster/internal/param"
  20. rpcLogstash "github.com/mhaya/game/game_cluster/internal/rpc/logstash"
  21. "github.com/mhaya/game/game_cluster/nodes/webadmin/common"
  22. "github.com/mhaya/game/game_cluster/nodes/webadmin/entity"
  23. mhayaLogger "github.com/mhaya/logger"
  24. "go.mongodb.org/mongo-driver/bson"
  25. "go.mongodb.org/mongo-driver/mongo"
  26. )
  27. var (
  28. json = jsoniter.ConfigCompatibleWithStandardLibrary
  29. )
  30. func Auth(app cfacade.IApplication) gin.HandlerFunc {
  31. return func(c *gin.Context) {
  32. // 请求开始时间
  33. startTime := mhayaTime.Now().UnixMilli()
  34. tokenString := ""
  35. roleId := ""
  36. var err error
  37. defer func() {
  38. sendLogRecord(c, app, tokenString, roleId, startTime)
  39. }()
  40. tokenString = c.GetHeader("Token")
  41. if tokenString == "" {
  42. common.PackUnauthorizedResult(c, code.UnauthorizedError, "token is empty")
  43. return
  44. }
  45. roleId, err = mdb.RDB.Get(context.Background(), tokenString).Result()
  46. if err != nil && err != redis.Nil {
  47. mhayaLogger.Warnf("Auth Get error: %s", err.Error())
  48. common.PackUnauthorizedResult(c, code.InternalError, "token is empty")
  49. return
  50. }
  51. if roleId == "" {
  52. common.PackUnauthorizedResult(c, code.UnauthorizedError, "token is invalid")
  53. return
  54. }
  55. if roleId != constant.AdminAccess {
  56. urlAccess, err := mdb.RDB.HGet(context.Background(), common.GetTokenKey(tokenString), c.Request.URL.Path).Result()
  57. if err != nil {
  58. mhayaLogger.Warnf("Auth HGet s error: %s", err.Error())
  59. common.PackUnauthorizedResult(c, code.InternalError, "")
  60. return
  61. }
  62. // 检查url权限
  63. if urlAccess == "" {
  64. common.PackUnauthorizedResult(c, code.UnauthorizedError, "token is no auth")
  65. return
  66. }
  67. // 非管理员需要进行ip校验
  68. openIpWhitelist := app.Settings().Get("open_ip_whitelist").ToBool()
  69. if openIpWhitelist {
  70. err = checkIPWhitelist(c)
  71. if err != nil {
  72. mhayaLogger.Warnf("Auth checkIPWhitelist error: %s", err.Error())
  73. common.PackForbiddenResult(c, code.ForbiddenError, "ip is no auth")
  74. return
  75. }
  76. }
  77. }
  78. adminAccess, err := mdb.RDB.HGet(context.Background(), common.GetTokenKey(tokenString), constant.AdminAccess).Result()
  79. if err != nil {
  80. mhayaLogger.Warnf("Auth HGet ss error: %s", err.Error())
  81. common.PackUnauthorizedResult(c, code.InternalError, "")
  82. return
  83. }
  84. // 检查管理员权限
  85. if adminAccess == "" {
  86. common.PackUnauthorizedResult(c, code.UnauthorizedError, "token is no auth")
  87. return
  88. }
  89. c.Next()
  90. }
  91. }
  92. // checkIP
  93. func checkIPWhitelist(c *gin.Context) error {
  94. // 获取请求的ip
  95. ip := c.ClientIP()
  96. var whitelistModel *models.Whitelist
  97. collection := mdb.MDB.Collection(whitelistModel.TableName())
  98. // 设置超时时间
  99. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  100. defer cancel() // 确保在函数退出时取消上下文
  101. // 示例:查询 IP 是否在白名单中
  102. err := collection.FindOne(ctx, bson.M{"ip": ip}).Decode(&whitelistModel)
  103. if err != nil && err != mongo.ErrNoDocuments {
  104. return err
  105. }
  106. // 根据查询结果决定是否允许访问
  107. if whitelistModel == nil {
  108. return errors.New("IP not in whitelist") // 拒绝访问
  109. }
  110. return nil // 允许访问
  111. }
  112. func sendLogRecord(c *gin.Context, app cfacade.IApplication, tokenString, roleId string, startTime int64) {
  113. userName, _ := mdb.RDB.Get(context.Background(), common.GetUserNameKey(tokenString)).Result()
  114. nodeId := app.NodeId()
  115. req, err := packBackendOperationEventReq(nodeId, &eventmodels.BackendOperationEventContent{
  116. UserBasic: eventmodels.UserBasic{
  117. UserName: userName,
  118. IsRobot: false,
  119. },
  120. EventBasic: eventmodels.EventBasic{
  121. ServerId: nodeId,
  122. IsSuccess: func() bool {
  123. return c.Writer.Status() == http.StatusOK
  124. }(),
  125. CreateAt: mhayaTime.Now().Unix(),
  126. },
  127. RoleId: roleId,
  128. Path: c.Request.URL.Path,
  129. Method: c.Request.Method,
  130. StatusCode: c.Writer.Status(),
  131. Dur: mhayaTime.Now().UnixMilli() - startTime,
  132. ClientIP: c.ClientIP(),
  133. ErrorMessage: c.Errors.ByType(gin.ErrorTypePrivate).String(),
  134. })
  135. if err != nil {
  136. mhayaLogger.Warnf("sendLogRecord packBackendOperationEventReq error: %s, token: %s", err.Error(), tokenString)
  137. return
  138. }
  139. rpcLogstash.HandleLogRecord(app, req)
  140. }
  141. func packBackendOperationEventReq(nodeId string, content *eventmodels.BackendOperationEventContent) (*param.HandleLogReq, error) {
  142. bytes, err := json.Marshal(content)
  143. if err != nil {
  144. return nil, err
  145. }
  146. return &param.HandleLogReq{
  147. ServerId: nodeId,
  148. EventName: content.EventName(),
  149. JsonContent: string(bytes),
  150. }, nil
  151. }
  152. func loginRecordMiddleware(app cfacade.IApplication) gin.HandlerFunc {
  153. return func(c *gin.Context) {
  154. // 请求开始时间
  155. startTime := mhayaTime.Now().UnixMilli()
  156. body, err := io.ReadAll(c.Request.Body)
  157. if err != nil {
  158. mhayaLogger.Warnf("loginRecordMiddleware ReadAll Request.Body error: %s", err.Error())
  159. return
  160. }
  161. // 关闭body
  162. defer c.Request.Body.Close()
  163. var reqBody entity.AdminLoginReq
  164. err = json.Unmarshal(body, &reqBody)
  165. if err != nil {
  166. mhayaLogger.Warnf("loginRecordMiddleware Unmarshal Request.Body error: %s", err.Error())
  167. return
  168. }
  169. // 写回请求体,以便其他中间件或路由可以正常读取
  170. c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
  171. c.Next()
  172. nodeId := app.NodeId()
  173. req, err := packBackendOperationEventReq(nodeId, &eventmodels.BackendOperationEventContent{
  174. UserBasic: eventmodels.UserBasic{
  175. UserName: reqBody.Username,
  176. IsRobot: false,
  177. },
  178. EventBasic: eventmodels.EventBasic{
  179. ServerId: nodeId,
  180. IsSuccess: func() bool {
  181. return c.Writer.Status() == http.StatusOK
  182. }(),
  183. CreateAt: mhayaTime.Now().Unix(),
  184. },
  185. Path: c.Request.URL.Path,
  186. Method: c.Request.Method,
  187. StatusCode: c.Writer.Status(),
  188. Dur: mhayaTime.Now().UnixMilli() - startTime,
  189. ClientIP: c.ClientIP(),
  190. ErrorMessage: c.Errors.ByType(gin.ErrorTypePrivate).String(),
  191. })
  192. if err != nil {
  193. mhayaLogger.Warnf("loginRecordMiddleware packBackendOperationEventReq error: %s", err.Error())
  194. return
  195. }
  196. rpcLogstash.HandleLogRecord(app, req)
  197. }
  198. }