成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

100行代碼實(shí)現(xiàn)審計(jì)日志中間件

開發(fā) 前端
個(gè)人認(rèn)為有以下幾個(gè)優(yōu)勢:(1)中間件的方式可靈活地匹配路由組,從而靈活地指定需要記錄日志的路由組;(2)同一個(gè)路由組中通過context value 來區(qū)分接口是否需要記錄操作日志;(3)業(yè)務(wù)處理函數(shù)中可靈活配置需記錄內(nèi)容,不需集中處理。

本文轉(zhuǎn)載自微信公眾號「小小平頭哥」,作者小小平頭哥。轉(zhuǎn)載本文請聯(lián)系小小平頭哥公眾號。

審計(jì)日志管理是我們在web系統(tǒng)開發(fā)中的常見的模塊,雖然它有時(shí)并不屬于業(yè)務(wù)模塊的范疇,但對于系統(tǒng)整體來說卻十分關(guān)鍵,用戶的操作(尤其是關(guān)鍵操作)、用戶的登錄,我們的系統(tǒng)都應(yīng)加以記錄,以便后續(xù)溯源。

日志管理的方案可以看到很多,本文介紹的是一種基于Golang Gin框架的自定義中間件的實(shí)現(xiàn)方案,為大家拋磚引玉了。

個(gè)人認(rèn)為有以下幾個(gè)優(yōu)勢:

(1)中間件的方式可靈活地匹配路由組,從而靈活地指定需要記錄日志的路由組;

(2)同一個(gè)路由組中通過context value 來區(qū)分接口是否需要記錄操作日志;

(3)業(yè)務(wù)處理函數(shù)中可靈活配置需記錄內(nèi)容,不需集中處理。

本文轉(zhuǎn)載自微信公眾號「小小平頭哥」,作者小小平頭哥。轉(zhuǎn)載本文請聯(lián)系小小平頭哥公眾號。

01整體流程

1) 中間件函數(shù)整體的流程

圖片圖片

2) 業(yè)務(wù)函數(shù)流程

圖片圖片

02代碼實(shí)現(xiàn)

1) 中間件函數(shù)實(shí)現(xiàn)

type Response struct {
  Code int `json:"code" bson:"code"`
}
type bodyLogWriter struct {
  gin.ResponseWriter
  body *bytes.Buffer
}


func (w bodyLogWriter) Write(b []byte) (int, error) {
  w.body.Write(b)
  return w.ResponseWriter.Write(b)
}


const (
  HttpRespSuccessCode = 0
)


// Logger 日志記錄
func Logger() gin.HandlerFunc {
  return func(c *gin.Context) {
   //備份請求體
    blw := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
    c.Writer = blw
    //繼續(xù)執(zhí)行請求
    c.Next()
    //判斷記錄標(biāo)志
    needToLog, ok := c.Get("need_to_log")
    if !ok {
      log.Warn("獲取是否需要記錄日志失敗")
      return
    }
    if !needToLog.(bool) {
      return
    }
    //也可以在這兒加入白名單 判斷是否是不需記錄的URL
    /*
      url := c.Request.RequestURI
      if strings.Index(url, "logout") > -1 ||
        strings.Index(url, "login") > -1 {
        return
      }
    */
    // 獲取請求的HTTP狀態(tài)碼
    statusCode := c.Writer.Status()
    // 獲取請求IP
    clientIP := common.GetClientIP(c)
    isSuccess := false
    //若HTTP狀態(tài)碼為200
    if c.Writer.Status() == http.StatusOK {
      var resp Response
      // 獲取返回的數(shù)據(jù)
      err := json.Unmarshal(blw.body.Bytes(), &resp)
      if err != nil {
        log.Warn("Logs Operation Unmarshal Error: %s", err.Error())
        return
      }
      //判斷操作是否成功 需結(jié)合業(yè)務(wù)函數(shù)的返回值結(jié)構(gòu)
      if resp.Code == HttpRespSuccessCode {
        isSuccess = true
      }
    }
    if statusCode != http.StatusNotFound {
      SetDBLog(c, clientIP, isSuccess)
    }
  }
}


// SetDBLog 寫入日志表
func SetDBLog(c *gin.Context, clientIP string, status bool) {
  user, ok := c.Get("user")
  if !ok {
    log.Warn("審計(jì)日志-獲取用戶名失敗")
  }
  //日志格式化 然后入庫
  logInfo := table.Logs{}
  //構(gòu)造日志ID 可使用其他方式替代
  logInfo.LogID = NewNanoid()
  if user != nil {
    logInfo.Username = user.(string)
  }
  operatorType, exist := c.Get("operation_type")
  if exist {
    logInfo.OperationType = operatorType.(string)
  }
  logInfo.IP = clientIP
  operation, exist := c.Get("operation")
  if exist {
    logInfo.Description = operation.(string)
  }
  if status == true {
    logInfo.Description = logInfo.Description + "成功"
  } else {
    logInfo.Description = logInfo.Description + "失敗"
  }
  //日志入庫
  err := InsertLog(logInfo)
  if err != nil {
    log.Warn("InsertLog %s error, %s", logInfo.LogID, err.Error())
  }
}


// InsertLog 插入log
func InsertLog(logs table.Logs) error {


}


2) 業(yè)務(wù)函數(shù)實(shí)現(xiàn)

func (User) UserLoginOut(c *ctx.Context) {
  //設(shè)定記錄日志標(biāo)志
  c.Set("need_to_log", true)
  //設(shè)定操作類型
  c.Set("operation_type", "用戶退出登錄")
  //設(shè)定具體操作
  c.Set("operation", "用戶退出登錄")
  c.Success()
}

3) 路由組應(yīng)用

//設(shè)定路由組
  UserRouter := apiV1Group.Group("users")
  //為路由組應(yīng)用中間件
  UserRouter.Use(middleware.Logger())


03注意事項(xiàng)

1) 中間件處理函數(shù)中的備份原始請求體很重要,否則可能會(huì)出現(xiàn)業(yè)務(wù)代碼無法獲取請求參數(shù)的情況;

  1. 中間件的報(bào)錯(cuò)不應(yīng)影響原有業(yè)務(wù)邏輯。

原文鏈接:https://mp.weixin.qq.com/s/7HAVAAst5IyywLxdNdTQ5g

責(zé)任編輯:武曉燕 來源: 小小平頭哥
相關(guān)推薦

2014-06-20 09:18:54

Dustjs中間件

2015-12-21 14:56:12

Go語言Http網(wǎng)絡(luò)協(xié)議

2011-05-24 15:10:48

2021-02-11 08:21:02

中間件開發(fā)CRUD

2020-06-28 09:20:33

代碼開發(fā)Go

2016-11-11 21:00:46

中間件

2018-02-01 10:19:22

中間件服務(wù)器系統(tǒng)

2018-07-29 12:27:30

云中間件云計(jì)算API

2010-03-24 17:59:20

2012-11-30 10:21:46

移動(dòng)中間件

2009-06-16 15:55:06

JBoss企業(yè)中間件

2023-10-24 07:50:18

消息中間件MQ

2023-06-29 10:10:06

Rocket MQ消息中間件

2010-04-13 10:37:47

核高基中間件

2022-09-21 16:09:28

消息中間件

2021-07-19 07:55:24

Redux中間件原理

2011-10-24 07:41:38

SOA中間件應(yīng)用服務(wù)器

2021-04-22 06:13:41

Express 中間件原理中間件函數(shù)

2024-12-09 00:00:15

Gin框架中間件

2015-02-07 21:52:45

PaaS中間件
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产一级一级国产 | 四虎av电影 | 国产精品区二区三区日本 | 久草视频在线播放 | www.婷婷| 亚洲成人在线视频播放 | 国产一卡二卡三卡 | h视频在线播放 | 欧美一区二区在线免费观看 | 超碰在线免费公开 | 国产在线一区二区 | 国产91精品久久久久久久网曝门 | 羞羞视频在线观看 | 免费啪啪| 久久午夜国产精品www忘忧草 | 激情 一区 | 三级黄视频在线观看 | 久久精品综合 | 精品久久久久久亚洲精品 | 国产一区亚洲 | 亚洲精品电影网在线观看 | 久草网址| 欧美激情国产精品 | 欧美激情视频一区二区三区在线播放 | 亚洲一区二区中文字幕 | 中文字幕第7页 | 午夜影院在线观看版 | 91精品国产91久久综合桃花 | 男人亚洲天堂 | 国产黄色在线观看 | 日韩中文字幕一区 | 亚洲电影免费 | 性欧美精品一区二区三区在线播放 | 欧美精品在线一区二区三区 | a在线视频| 成人免费共享视频 | 久久中文字幕在线 | 啪一啪| 久草新在线| 国产乱码精品1区2区3区 | 免费福利视频一区二区三区 |