From f864064d11805a5f5cf5a08d02957a9c32cad8f9 Mon Sep 17 00:00:00 2001 From: 537yaha <2930134478@qq.com> Date: Tue, 31 Mar 2026 17:14:49 +0800 Subject: [PATCH] =?UTF-8?q?ip=E8=BF=87=E9=95=BF=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/models/user.go | 2 +- backend/utils/request.go | 36 +++++++++++++++++++++++++++++------- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/backend/models/user.go b/backend/models/user.go index 7fb2868..8045d72 100644 --- a/backend/models/user.go +++ b/backend/models/user.go @@ -35,7 +35,7 @@ type Conversation struct { Browser string `json:"browser" gorm:"type:varchar(100)"` // 浏览器信息 OS string `json:"os" gorm:"type:varchar(100)"` // 操作系统 Language string `json:"language" gorm:"type:varchar(50)"` // 语言 - IPAddress string `json:"ip_address" gorm:"type:varchar(50)"` // IP地址 + IPAddress string `json:"ip_address" gorm:"type:varchar(255)"` // IP地址(含 IPv6;经代理时仅存 X-Forwarded-For 首段) Location string `json:"location" gorm:"type:varchar(200)"` // 位置 // 联系信息字段(客服手动添加) Email string `json:"email" gorm:"type:varchar(255)"` // 邮箱 diff --git a/backend/utils/request.go b/backend/utils/request.go index c8fc8c2..b674e9c 100644 --- a/backend/utils/request.go +++ b/backend/utils/request.go @@ -9,16 +9,38 @@ import ( // GetClientIP 获取客户端 IP 地址(考虑代理情况) func GetClientIP(c *gin.Context) string { // 优先从 X-Forwarded-For 获取(适用于代理/负载均衡) - ip := strings.TrimSpace(c.GetHeader("X-Forwarded-For")) - if ip != "" { - return ip + // 标准格式为「客户端, 代理1, 代理2」;数据库存 varchar 时整串会超长,只取第一项。 + xff := strings.TrimSpace(c.GetHeader("X-Forwarded-For")) + if xff != "" { + if first := firstXForwardedForClient(xff); first != "" { + return sanitizeIPForDB(first) + } } - // 从 X-Real-IP 获取 - ip = strings.TrimSpace(c.GetHeader("X-Real-IP")) + ip := strings.TrimSpace(c.GetHeader("X-Real-IP")) if ip != "" { - return ip + return sanitizeIPForDB(ip) } - return c.ClientIP() + return sanitizeIPForDB(c.ClientIP()) +} + +func firstXForwardedForClient(xff string) string { + for _, part := range strings.Split(xff, ",") { + s := strings.TrimSpace(part) + if s != "" { + return s + } + } + return "" +} + +// sanitizeIPForDB 限制长度,避免异常头或未来字段变更再次撑爆列。 +func sanitizeIPForDB(ip string) string { + ip = strings.TrimSpace(ip) + const maxLen = 255 + if len(ip) > maxLen { + return ip[:maxLen] + } + return ip } // ParseUserAgent 从 User-Agent 字符串中解析浏览器和操作系统