签入版本

This commit is contained in:
2026-09-16 13:28:20 +08:00
parent 6cd5e80de0
commit c97d87847f
410 changed files with 68726 additions and 0 deletions
@@ -0,0 +1,133 @@
# IP 归属地解析
:::tip 说明
`src/common/utils/ip2region.py` 基于 [ip2region](https://github.com/lionsoul2014/ip2region) 离线数据库,提供 IP 地址到省市区的归属地查询能力,无需网络请求。`src/common/utils/helpers.py` 中的 `detect_os` 和 `detect_browser` 提供 User-Agent 解析。
:::
## 核心接口
### get_ip_location — 获取归属地文本
```python
from common.utils.ip2region import get_ip_location
location = get_ip_location("114.114.114.114")
# 返回: "中国 江苏省 南京市"
location = get_ip_location("8.8.8.8")
# 返回: "United States California"
location = get_ip_location("10.0.0.1")
# 返回: "内网IP"
```
### get_ip_region — 获取完整区域信息
```python
from common.utils.ip2region import get_ip_region
info = get_ip_region("114.114.114.114")
# 返回: {"country": "中国", "province": "江苏省", "city": "南京市", "isp": "南京信风", "country_code": "CN"}
```
## UA 解析
位于 `src/common/utils/helpers.py`:
```python
from common.utils.helpers import detect_os, detect_browser
# 解析操作系统
os_name = detect_os("Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...")
# 返回: "Windows 10.0"
# 解析浏览器
browser_name = detect_browser("Mozilla/5.0 ... Chrome/120.0.0.0 ...")
# 返回: "Chrome 120.0"
```
## 应用场景
### 操作日志记录
```python
# src/common/middleware/operation_log.py
ip = get_ip_location(handler.request.remote_ip)
os_name = detect_os(ua)
browser_name = detect_browser(ua)
```
### 登录日志记录
```python
# src/common/middleware/login_log.py
ip = get_ip_location(handler.request.remote_ip)
os_name = detect_os(ua)
browser_name = detect_browser(ua)
```
## 预热机制
ip2region.xdb 文件约 10MB,首次查询时加载。应用启动时预热避免首次请求延迟:
```python
# src/bootstrap.py
from common.utils.ip2region import preload
preload() # 预加载 xdb 文件到内存
```
## 降级策略
| 异常场景 | 降级行为 |
|:---------|:---------|
| xdb 文件不存在 | 返回 `"未知"` |
| xdb 加载失败 | 返回 `"未知"` |
| 畸形 IP 地址 | 返回 `"未知"` |
| 内网/保留地址 | 返回 `"内网IP"` |
所有查询接口均采用 fail-open 降级策略,查询失败绝不向上抛异常,保证日志落库不受影响。
## xdb 数据库更新
ip2region.xdb 离线数据库需要定期更新以覆盖新增的 IP 段:
```bash
# 1. 下载最新 xdb 文件
# GitHub: https://github.com/lionsoul2014/ip2region/tree/master/data
# 将 ip2region.xdb 放到 static/ 目录下
# 2. 重启应用即可生效(启动时自动加载)
poetry run python app.py --port=8041
```
:::tip 数据库格式
xdb 是 ip2region 的二进制索引格式,约 10MB,支持微秒级查询。文件路径在 `src/common/utils/ip2region.py` 中配置。
:::
## 完整日志记录示例
操作日志和登录日志中记录完整的客户端信息:
```python
from common.utils.ip2region import get_ip_location
from common.utils.helpers import detect_os, detect_browser
# 获取客户端信息
ip = handler.request.remote_ip
ua = handler.request.headers.get("User-Agent", "")
location = get_ip_location(ip)
os_name = detect_os(ua)
browser_name = detect_browser(ua)
# 记录到日志
log_data = {
"ip": ip, # "114.114.114.114"
"ip_location": location, # "中国 江苏省 南京市"
"os": os_name, # "Windows 10.0"
"browser": browser_name, # "Chrome 120.0"
}
```
## 总结
IP 归属地解析基于 ip2region 离线数据库,零网络依赖。提供 `get_ip_location`(文本)和 `get_ip_region`(结构化)两个查询接口,配合 `detect_os` / `detect_browser` 为操作日志和登录日志提供完整的客户端身份信息。xdb 文件需定期更新以覆盖新增 IP 段。