package midware import ( "bytes" "encoding/json" "fmt" "io" "net/http" "reflect" "runtime" "strings" "time" "ems.agt/lib/core/utils/parse" "ems.agt/lib/dborm" "ems.agt/src/framework/constants/common" "ems.agt/src/framework/middleware/collectlogs" "ems.agt/src/framework/utils/ip2region" "ems.agt/src/modules/system/model" "ems.agt/src/modules/system/service" ) // 敏感属性字段进行掩码 var maskProperties []string = []string{ "password", "oldPassword", "newPassword", "confirmPassword", } // LogOperate 操作日志搜集 func LogOperate(options collectlogs.Options) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { startTime := time.Now() // 只对前端发送的数据进行记录 appCodeStr := r.Header.Get("X-App-Code") if appCodeStr == "" { next.ServeHTTP(w, r) return } // 函数名 funcName := runtime.FuncForPC(reflect.ValueOf(next).Pointer()).Name() lastDotIndex := strings.LastIndex(funcName, "/") funcName = funcName[lastDotIndex+1:] // 用户名 username := "-" accessToken := r.Header.Get("AccessToken") if accessToken != "" { // 验证令牌 == 这里直接查数据库session se, _ := dborm.XormUpdateSessionShakeTime(accessToken) username = se.AccountId } // 解析ip地址 ip := strings.Split(r.RemoteAddr, ":")[0] ipaddr := ip2region.ClientIP(ip) location := ip2region.RealAddressByIp(ipaddr) // 操作日志记录 operLog := model.SysLogOperate{ Title: options.Title, BusinessType: options.BusinessType, OperatorType: collectlogs.OPERATOR_TYPE_MANAGE, Method: funcName, OperURL: r.RequestURI, RequestMethod: r.Method, OperIP: ipaddr, OperLocation: location, OperName: username, DeptName: "", } // 是否需要保存request,参数和值 if options.IsSaveRequestData && (r.Method == "POST" || r.Method == "PUT") { // 读取请求体内容 body, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } // 解析json内参数 var bodyArgs map[string]any _ = json.Unmarshal(bytes.Clone(body), &bodyArgs) // 将请求体内容存储在临时缓冲区中 buffer := bytes.NewBuffer(body) r.Body = io.NopCloser(buffer) params := bodyArgs for k, v := range params { // 敏感属性字段进行掩码 for _, s := range maskProperties { if s == k { params[k] = parse.SafeContent(v.(string)) break } } } jsonStr, _ := json.Marshal(params) paramsStr := string(jsonStr) if len(paramsStr) > 2000 { paramsStr = paramsStr[:2000] } operLog.OperParam = paramsStr } next.ServeHTTP(w, r) // 响应内容长度和状态码作为结果 str := strings.TrimSuffix(fmt.Sprintf("%v", w), "}") strArr := strings.Split(str, " ") size := strArr[1] status := strArr[2] // 响应状态 if status == "200" { operLog.Status = common.STATUS_YES } else { operLog.Status = common.STATUS_NO } // 是否需要保存response,参数和值 if options.IsSaveResponseData { contentDisposition := w.Header().Get("Content-Disposition") contentType := w.Header().Get("Content-Type") content := contentType + contentDisposition msg := fmt.Sprintf(`{"status":"%s","size":"%s","content-type":"%s"}`, status, size, content) operLog.OperMsg = msg } // 日志记录时间 duration := time.Since(startTime) operLog.CostTime = duration.Milliseconds() operLog.OperTime = time.Now().UnixMilli() // 保存操作记录到数据库 service.NewSysLogOperateImpl.InsertSysLogOperate(operLog) }) } }