Files
nms_cxy/lib/midware/operate_log.go

138 lines
3.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package midware
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"reflect"
"runtime"
"strings"
"time"
"be.ems/lib/core/ctx"
"be.ems/src/framework/constants/common"
"be.ems/src/framework/middleware/collectlogs"
"be.ems/src/framework/utils/ip2region"
"be.ems/src/framework/utils/parse"
"be.ems/src/modules/system/model"
"be.ems/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 := ctx.LoginUserToUserName(r)
// 解析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" || status == "204" {
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)
})
}
}