From a21afb2c0ce32f7d8f66056d4fa03da577607c3f Mon Sep 17 00:00:00 2001 From: samwaf Date: Tue, 25 Mar 2025 09:59:21 +0800 Subject: [PATCH] fix:encoding asset --- utils/http_check.go | 49 +++++++++++++++++++++---------- wafenginecore/content_encoding.go | 18 ++++++++++-- wafenginecore/wafengine.go | 26 ++++++++-------- 3 files changed, 63 insertions(+), 30 deletions(-) diff --git a/utils/http_check.go b/utils/http_check.go index 472642a..33de9ec 100644 --- a/utils/http_check.go +++ b/utils/http_check.go @@ -1,22 +1,12 @@ package utils -import "strings" - -// IsContent 是否是内容 -func IsContent(contentType string) bool { - var allowedSortFields = []string{"application/json", "text/xml", "application/xml", - "text/plain", "text/html", "text/csv", "application/html"} - - for _, allowedField := range allowedSortFields { - if strings.Contains(contentType, allowedField) { - return true - } - } - return false -} +import ( + "net/http" + "strings" +) // IsStaticAssist 是否是静态资源 -func IsStaticAssist(contentType string) bool { +func IsStaticAssist(res *http.Response, contentType string) bool { var allowedSortFields = []string{"application/javascript", "text/css", "image/jpeg", "image/png", "image/gif", "image/x-icon", "text/js"} @@ -25,5 +15,34 @@ func IsStaticAssist(contentType string) bool { return true } } + // 检查请求的Accept头,判断是否为资源类型请求 + if res.Request != nil { + acceptHeader := res.Request.Header.Get("Accept") + if acceptHeader != "" { + // 检查Accept头是否主要请求图片或其他资源类型 + isResourceRequest := strings.Contains(acceptHeader, "image/") || + strings.Contains(acceptHeader, "font/") || + strings.Contains(acceptHeader, "audio/") || + strings.Contains(acceptHeader, "video/") + return isResourceRequest + } + + // 检查Sec-Fetch-Dest头,这是一个更明确的指示 + secFetchDest := res.Request.Header.Get("Sec-Fetch-Dest") + if secFetchDest == "image" || secFetchDest == "font" || + secFetchDest == "audio" || secFetchDest == "video" || + secFetchDest == "style" { + return true + } + } + //如果检测资源后发现还存在,那么进行判断处理 + var textFields = []string{"application/json", "text/xml", "application/xml", + "text/plain", "text/html", "text/csv", "application/html"} + + for _, textField := range textFields { + if strings.Contains(contentType, textField) { + return false + } + } return false } diff --git a/wafenginecore/content_encoding.go b/wafenginecore/content_encoding.go index 73ecbae..7c0ed70 100644 --- a/wafenginecore/content_encoding.go +++ b/wafenginecore/content_encoding.go @@ -20,7 +20,14 @@ import ( ) // 返回内容前依据情况进行返回压缩数据 -func (waf *WafEngine) compressContent(res *http.Response, inputBytes []byte) (respBytes []byte, err error) { +func (waf *WafEngine) compressContent(res *http.Response, isStaticAssist bool, inputBytes []byte) (respBytes []byte, err error) { + + // 如果是静态资源响应或资源类型请求,直接返回原始内容 + if isStaticAssist { + zlog.Debug("静态资源或资源类型请求,跳过编码转换") + return inputBytes, nil + } + // 首先检查Content-Type头中是否明确指定了字符集 contentType := res.Header.Get("Content-Type") var encodedBytes []byte = inputBytes @@ -70,13 +77,20 @@ func (waf *WafEngine) compressContent(res *http.Response, inputBytes []byte) (re } // 获取原始内容 -func (waf *WafEngine) getOrgContent(resp *http.Response) (cntBytes []byte, err error) { +func (waf *WafEngine) getOrgContent(resp *http.Response, isStaticAssist bool) (cntBytes []byte, err error) { bodyBytes, err := io.ReadAll(resp.Body) if err != nil { return bodyBytes, fmt.Errorf("读取原始响应体失败: %v", err) } // 重新设置响应体,以便后续处理 resp.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) + + // 如果是静态资源响应或资源类型请求,直接返回原始内容 + if isStaticAssist { + zlog.Debug("静态资源或资源类型请求,跳过编码转换") + return bodyBytes, nil + } + // 根据内容编码处理压缩 var bodyReader io.Reader switch resp.Header.Get("Content-Encoding") { diff --git a/wafenginecore/wafengine.go b/wafenginecore/wafengine.go index 5c2e5ed..2289fec 100644 --- a/wafenginecore/wafengine.go +++ b/wafenginecore/wafengine.go @@ -600,6 +600,14 @@ func (waf *WafEngine) modifyResponse() func(*http.Response) error { weblogfrist.STATUS = resp.Status weblogfrist.STATUS_CODE = resp.StatusCode + //返回内容的类型 + respContentType := strings.ToLower(resp.Header.Get("Content-Type")) + respContentType = strings.Replace(respContentType, "; charset=utf-8", "", -1) + respContentType = strings.Replace(respContentType, "; charset=gbk", "", -1) + + //记录静态日志 + isStaticAssist := utils.IsStaticAssist(resp, respContentType) + ldpFlag := false // 将请求URL转为小写,用于不区分大小写的比较 lowerRequestURI := strings.ToLower(resp.Request.RequestURI) @@ -633,10 +641,10 @@ func (waf *WafEngine) modifyResponse() func(*http.Response) error { } } if ldpFlag == true { - orgContentBytes, responseEncodingError := waf.getOrgContent(resp) + orgContentBytes, responseEncodingError := waf.getOrgContent(resp, isStaticAssist) if responseEncodingError == nil { newPayload := []byte("" + utils.DeSenText(string(orgContentBytes))) - finalCompressBytes, _ := waf.compressContent(resp, newPayload) + finalCompressBytes, _ := waf.compressContent(resp, isStaticAssist, newPayload) resp.Body = io.NopCloser(bytes.NewBuffer(finalCompressBytes)) // head 修改追加内容 @@ -648,20 +656,12 @@ func (waf *WafEngine) modifyResponse() func(*http.Response) error { } } - //返回内容的类型 - respContentType := strings.ToLower(resp.Header.Get("Content-Type")) - respContentType = strings.Replace(respContentType, "; charset=utf-8", "", -1) - respContentType = strings.Replace(respContentType, "; charset=gbk", "", -1) - - //记录静态日志 - isStaticAssist := utils.IsStaticAssist(respContentType) - isText := utils.IsContent(respContentType) //记录响应body - if isText && resp.Body != nil && resp.Body != http.NoBody { + if !isStaticAssist && resp.Body != nil && resp.Body != http.NoBody { //编码转换,自动检测网页编码 resp *http.Response - orgContentBytes, responseEncodingError := waf.getOrgContent(resp) + orgContentBytes, responseEncodingError := waf.getOrgContent(resp, isStaticAssist) if responseEncodingError == nil { if global.GCONFIG_RECORD_RESP == 1 { if resp.ContentLength < global.GCONFIG_RECORD_MAX_RES_BODY_LENGTH { @@ -696,7 +696,7 @@ func (waf *WafEngine) modifyResponse() func(*http.Response) error { } } //将数据在回写上去 - finalCompressBytes, _ := waf.compressContent(resp, orgContentBytes) + finalCompressBytes, _ := waf.compressContent(resp, isStaticAssist, orgContentBytes) resp.Body = io.NopCloser(bytes.NewBuffer(finalCompressBytes)) resp.ContentLength = int64(len(finalCompressBytes)) resp.Header.Set("Content-Length", strconv.FormatInt(int64(len(finalCompressBytes)), 10))