签入版本
This commit is contained in:
@@ -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 段。
|
||||
Reference in New Issue
Block a user