Files
FileShare/server/internal/audit/ua.go
T
SKYMirror 9686fe887a FileCodeBox Go 重写版 v2.5.6(安全审计修复版)
Go 1.27.1 (Gin+GORM) + Vue 3 文件快传服务:

- 安全审计全部修复(docs/security-audit-2026-09-05.md):
  bcrypt 密码哈希与自动升级、presign 直传服务端大小/内容校验、
  全局请求体上限、依赖升级(govulncheck 0 命中)、janitor 后台清理、
  管理端审计动作落库、/admin CORS 收紧、通知内容白名单净化、
  会话默认 7 天、限流缓存故障降级、robots.txt 端点等
- 前端:取件链接复制修复(不再重复拼接提取码)、markdown 净化器加固
- Redis 支持库号(FCB_REDIS_DB / redis://…/db URL)
- 文档:docs/api/* 与 openapi.yaml 同步最新行为(robots.txt、
  提码 5 位起、chunk 32MiB 上限、admin 审计动作等)

验证:gofmt/go vet/go test 全绿;二进制端到端冒烟通过
2026-09-05 04:22:41 +08:00

85 lines
2.5 KiB
Go

package audit
import (
"strings"
)
// DeviceInfo 从 User-Agent 解析出的设备信息。
type DeviceInfo struct {
OS string // Windows/macOS/Android/iOS/Linux/Unknown
Browser string // Chrome/Firefox/Safari/Edge/Other
Type string // desktop/mobile/tablet/bot/other
}
// 动作常量。
const (
ActionUpload = "upload"
ActionDownload = "download"
// ActionAdmin 管理端敏感操作(登录/登出/配置/密码/引擎切换/文件删除等),
// L5:纳入审计以便追溯登录失败与配置变更。
ActionAdmin = "admin"
)
// 角色常量。
const (
ActorAdmin = "admin"
ActorGuest = "guest"
)
// botKeywords 常见爬虫/机器人标识。
var botKeywords = []string{"bot", "spider", "crawl", "slurp", "curl/", "wget", "python-requests", "go-http-client"}
// ParseUserAgent 解析 User-Agent 为设备信息(轻量规则,避免引入重依赖)。
func ParseUserAgent(ua string) DeviceInfo {
ua = strings.TrimSpace(ua)
lower := strings.ToLower(ua)
if ua == "" {
return DeviceInfo{OS: "Unknown", Browser: "Other", Type: "other"}
}
for _, kw := range botKeywords {
if strings.Contains(lower, kw) {
return DeviceInfo{OS: "Unknown", Browser: "Other", Type: "bot"}
}
}
info := DeviceInfo{OS: "Unknown", Browser: "Other", Type: "desktop"}
// 操作系统
switch {
case strings.Contains(lower, "windows"):
info.OS = "Windows"
case strings.Contains(lower, "iphone"), strings.Contains(lower, "ipod"):
info.OS = "iOS"
info.Type = "mobile"
case strings.Contains(lower, "ipad"):
info.OS = "iOS"
info.Type = "tablet"
case strings.Contains(lower, "mac os x"), strings.Contains(lower, "macintosh"):
info.OS = "macOS"
case strings.Contains(lower, "android"):
info.OS = "Android"
info.Type = "mobile"
if strings.Contains(lower, "tablet") || !strings.Contains(lower, "mobile") {
info.Type = "tablet"
}
case strings.Contains(lower, "linux"), strings.Contains(lower, "ubuntu"), strings.Contains(lower, "fedora"):
info.OS = "Linux"
}
// 浏览器(顺序重要:Edge/OPR 必须在 Chrome 之前判断)
switch {
case strings.Contains(lower, "edg/"), strings.Contains(lower, "edge/"):
info.Browser = "Edge"
case strings.Contains(lower, "opr/"), strings.Contains(lower, "opera"):
info.Browser = "Opera"
case strings.Contains(lower, "chrome/"), strings.Contains(lower, "crios/"):
info.Browser = "Chrome"
case strings.Contains(lower, "firefox/"), strings.Contains(lower, "fxios/"):
info.Browser = "Firefox"
case strings.Contains(lower, "safari/"):
info.Browser = "Safari"
}
return info
}