This repository has been archived on 2026-06-21. You can view files and clone it, but cannot push or open issues or pull requests.
Files
MetaLab/internal/session/ua.go
Victor_Jay d203447eb3 feat: 设置页新增登录管理 TAB
- Session 结构体新增 IP、UserAgent、Remark 字段,登录/注册时记录设备信息
- Store 接口新增 ListByUID、DeleteByUIDExclude 方法,MemoryStore 完整实现
- SessionManager 新增 ListByUID、DestroyOtherByUID、UpdateRemark 方法
- 新增 UA 轻量解析器(session/ua.go),提取浏览器/OS/设备类型
- 新增 settings_api_sessions.go,提供列表/踢出/一键踢出/备注 4 个 API
- 控制器层声明 sessionManager 最小接口(ISP),SettingsController 注入依赖
- Auth 中间件注入 sid 到 gin context,支持识别当前会话
- 设置页左侧导航增加登录管理入口,tab 白名单新增 sessions
- 前端实现设备列表展示(浏览器/OS/设备图标/IP/时间)、当前设备标识、备注输入、踢出按钮、一键踢出
- settings.css 新增会话管理全套样式及响应式适配
2026-05-30 23:58:37 +08:00

98 lines
2.7 KiB
Go
Raw 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 session
import "strings"
// DeviceInfo 从 User-Agent 解析出的设备摘要信息
type DeviceInfo struct {
Device string // 设备类型Desktop / Mobile / Tablet
OS string // 操作系统Windows 10 / macOS / Android 12 等
Browser string // 浏览器Chrome 120 / Firefox 121 / Safari 17 等
}
// ParseUA 从原始 User-Agent 字符串解析设备信息(轻量级,不引入第三方库)
func ParseUA(ua string) DeviceInfo {
info := DeviceInfo{Device: "Desktop"}
lower := strings.ToLower(ua)
// --- 操作系统 ---
switch {
case strings.Contains(lower, "windows nt 10"):
info.OS = "Windows 10/11"
case strings.Contains(lower, "windows nt 6.3"):
info.OS = "Windows 8.1"
case strings.Contains(lower, "windows nt 6.2"):
info.OS = "Windows 8"
case strings.Contains(lower, "windows nt 6.1"):
info.OS = "Windows 7"
case strings.Contains(lower, "windows"):
info.OS = "Windows"
case strings.Contains(lower, "mac os x"):
info.OS = "macOS"
if strings.Contains(lower, "iphone") {
info.OS = "iOS"
info.Device = "Mobile"
} else if strings.Contains(lower, "ipad") {
info.OS = "iPadOS"
info.Device = "Tablet"
}
case strings.Contains(lower, "android"):
info.OS = "Android"
info.Device = "Mobile"
if strings.Contains(lower, "tablet") || strings.Contains(lower, "ipad") {
info.Device = "Tablet"
}
case strings.Contains(lower, "iphone"):
info.OS = "iOS"
info.Device = "Mobile"
case strings.Contains(lower, "ipad"):
info.OS = "iPadOS"
info.Device = "Tablet"
case strings.Contains(lower, "linux"):
info.OS = "Linux"
case strings.Contains(lower, "cros"):
info.OS = "ChromeOS"
default:
info.OS = "Unknown"
}
// --- 浏览器 ---
switch {
case strings.Contains(lower, "edg/"):
info.Browser = "Edge"
info.Browser += extractVersion(ua, "Edg/")
case strings.Contains(lower, "chrome/") && !strings.Contains(lower, "edg/"):
info.Browser = "Chrome"
info.Browser += extractVersion(ua, "Chrome/")
case strings.Contains(lower, "firefox/"):
info.Browser = "Firefox"
info.Browser += extractVersion(ua, "Firefox/")
case strings.Contains(lower, "safari/") && !strings.Contains(lower, "chrome/"):
info.Browser = "Safari"
info.Browser += extractVersion(ua, "Version/")
default:
info.Browser = "Unknown"
}
return info
}
// extractVersion 从 UA 中提取主版本号
func extractVersion(ua, prefix string) string {
idx := strings.Index(ua, prefix)
if idx == -1 {
return ""
}
rest := ua[idx+len(prefix):]
dot := strings.Index(rest, ".")
if dot == -1 {
// 无点号,取到空格或结尾
sp := strings.Index(rest, " ")
if sp > 0 {
return " " + rest[:sp]
}
return ""
}
return " " + rest[:dot]
}