日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

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

來源: 責(zé)編: 時(shí)間:2023-11-28 09:36:34 250觀看
導(dǎo)讀本文轉(zhuǎn)載自微信公眾號(hào)「小小平頭哥」,作者小小平頭哥。轉(zhuǎn)載本文請(qǐng)聯(lián)系小小平頭哥公眾號(hào)。審計(jì)日志管理是我們?cè)趙eb系統(tǒng)開發(fā)中的常見的模塊,雖然它有時(shí)并不屬于業(yè)務(wù)模塊的范疇,但對(duì)于系統(tǒng)整體來說卻十分關(guān)鍵,用戶的操作(尤

本文轉(zhuǎn)載自微信公眾號(hào)「小小平頭哥」,作者小小平頭哥。轉(zhuǎn)載本文請(qǐng)聯(lián)系小小平頭哥公眾號(hào)。bK328資訊網(wǎng)——每日最新資訊28at.com

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

日志管理的方案可以看到很多,本文介紹的是一種基于Golang Gin框架的自定義中間件的實(shí)現(xiàn)方案,為大家拋磚引玉了。bK328資訊網(wǎng)——每日最新資訊28at.com

個(gè)人認(rèn)為有以下幾個(gè)優(yōu)勢(shì):bK328資訊網(wǎng)——每日最新資訊28at.com

(1)中間件的方式可靈活地匹配路由組,從而靈活地指定需要記錄日志的路由組;bK328資訊網(wǎng)——每日最新資訊28at.com

(2)同一個(gè)路由組中通過context value 來區(qū)分接口是否需要記錄操作日志;bK328資訊網(wǎng)——每日最新資訊28at.com

(3)業(yè)務(wù)處理函數(shù)中可靈活配置需記錄內(nèi)容,不需集中處理。bK328資訊網(wǎng)——每日最新資訊28at.com

本文轉(zhuǎn)載自微信公眾號(hào)「小小平頭哥」,作者小小平頭哥。轉(zhuǎn)載本文請(qǐng)聯(lián)系小小平頭哥公眾號(hào)。bK328資訊網(wǎng)——每日最新資訊28at.com

01整體流程

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

圖片圖片bK328資訊網(wǎng)——每日最新資訊28at.com

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

圖片圖片bK328資訊網(wǎng)——每日最新資訊28at.com

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) {   //備份請(qǐng)求體    blw := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}    c.Writer = blw    //繼續(xù)執(zhí)行請(qǐng)求    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      }    */    // 獲取請(qǐng)求的HTTP狀態(tài)碼    statusCode := c.Writer.Status()    // 獲取請(qǐng)求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 插入logfunc InsertLog(logs table.Logs) error {}


bK328資訊網(wǎng)——每日最新資訊28at.com

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())


bK328資訊網(wǎng)——每日最新資訊28at.com

03注意事項(xiàng)

1) 中間件處理函數(shù)中的備份原始請(qǐng)求體很重要,否則可能會(huì)出現(xiàn)業(yè)務(wù)代碼無法獲取請(qǐng)求參數(shù)的情況;bK328資訊網(wǎng)——每日最新資訊28at.com

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

原文鏈接:https://mp.weixin.qq.com/s/7HAVAAst5IyywLxdNdTQ5gbK328資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-34658-0.html100行代碼實(shí)現(xiàn)審計(jì)日志中間件

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: Springboot擴(kuò)展點(diǎn)之BeanDefinitionRegistryPostProcessor,你學(xué)會(huì)了嗎?

下一篇: 實(shí)現(xiàn)Eureka服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn),你學(xué)會(huì)了嗎?

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 主站蜘蛛池模板: 永城市| 习水县| 沾化县| 吴旗县| 海盐县| 夹江县| 永德县| 贵定县| 永州市| 五大连池市| 扶绥县| 铜山县| 平舆县| 鄂温| 呼玛县| 九龙城区| 竹山县| 禄劝| 吴桥县| 万年县| 哈密市| 临漳县| 鸡西市| 建昌县| 天祝| 屏东市| 白朗县| 成都市| 仲巴县| 宜昌市| 滦平县| 三都| 邛崃市| 霞浦县| 苗栗市| 河池市| 广丰县| 鄂伦春自治旗| 新巴尔虎右旗| 射洪县| 湄潭县|