This commit is contained in:
2026-02-08 18:49:14 -08:00
parent 709d657906
commit 28ada42ae5
14 changed files with 726 additions and 77 deletions
@@ -0,0 +1,54 @@
# ALIGNMENT: 检查设备登录 IP 逻辑
## 原始需求
用户询问:
> "检查一下 设备登录的时候 有检查IP 么"
> "我需要知道 有没有IP 目前数据库都没有IP"
## 项目现状分析 (Context Analysis)
1. **数据模型 (`user.Device`)**:
- 存在 `Ip` 字段 (`varchar(255)`).
- 定义在 `/internal/model/user/user.go`
2. **业务逻辑 (`DeviceLoginLogic.go`)**:
- 在代码逻辑中,确实尝试获取 `req.IP` 并保存到数据库。
- 创建新设备时:`deviceInfo.Ip = req.IP`
- 记录登录日志时:`LoginIP: req.IP`
3. **关键问题点 (Root Cause)**:
- 输入参数定义在 `internal/types/types.go`:
```go
type DeviceLoginRequest struct {
// ...
IP string `header:"X-Original-Forwarded-For"`
// ...
}
```
- **当前仅支持 `X-Original-Forwarded-For` 请求头**。
- 如果请求经过 Nginx、Cloudflare 等代理,但没有专门配置传递这个特定的 Header,或者使用的是标准的 `X-Forwarded-For` / `X-Real-IP`,后端获取到的 `req.IP` 将为空字符串。
- 这就是导致“数据库都没有IP”的直接原因。
## 疑问澄清 (Questions)
我们需要确认修复方案:
1. **是否只需支持标准 Header?**
- 建议改为优先获取 `X-Forwarded-For`,其次 `X-Real-IP`,最后才是 `X-Original-Forwarded-For` 或直连 IP。
- go-zero 框架通常可以通过配置或中间件处理 IP,或者我们在 struct tag 中调整。但 struct tag `header` 只能由 go-zero 的 rest 绑定一个特定的 key。
2. **是否需要记录 IP 归属地?**
- 目前逻辑只记录 IP 字符串,不解析归属地。需求中没提,暂时不作为重点,但可以确认一下。
## 建议方案
修改 `DeviceLoginRequest` 的定义可能不够灵活(Header key 是固定的)。
更好的方式是:
1. **移除 Struct Tag 绑定**(或者保留作为备选)。
2. **在 Logic 中显式获取 IP**
- 从 `l.ctx` (Context) 中获取 `http.Request` (如果 go-zero 支持)。
- 或者在 Middleware 中解析真实 IP 并放入 Context。
- 或者简单点,修改 Struct Tag 为最常用的 `X-Forwarded-For` (如果确定环境是这样配置的)。
**最快修复**:
将 `internal/types/types.go` 中的 `X-Original-Forwarded-For` 改为 `X-Forwarded-For` (或者根据实际网关配置修改)。
但通常建议使用工具函数解析多种 Header。
## 下一步 (Next Step)
请确认是否要我修改代码以支持标准的 IP 获取方式(如 `X-Forwarded-For`)?
@@ -0,0 +1,36 @@
# DESIGN: Device Login IP Fix
## 目标
修复设备登录时无法获取真实 IP (`req.IP` 为空) 的问题,导致数据库未存储 IP。
## 现状
- `internal/types/types.go` 定义了 `DeviceLoginRequest`,其中 `IP` 字段绑定的是 `X-Original-Forwarded-For`
- 实际环境中(Nginx/Cloudflare等)通常使用 `X-Forwarded-For`
## 方案选择
由于项目使用 `go-zero` 并且存在 `.api` 文件,**最佳实践**是修改 `.api` 文件并重新生成代码。
但考虑到我无法运行 `goctl` (或者环境可能不一致),如果不重新生成而直接改 `types.go`,虽然能即时生效,但下次生成会被覆盖。
**然而**,鉴于我之前的操作已经直接修改过 `types.go` (Invite Sales Time Filter),且项目看似允许直接修改(或用户负责生成),我将**优先修改 `.api` 文件** 以保持源头正确,同时**手动同步修改 `types.go`** 以确保立即生效。
## 变更范围
### 1. API 定义 (`apis/auth/auth.api`)
- 修改 `DeviceLoginRequest` struct。
-`header: X-Original-Forwarded-For` 改为 `header: X-Forwarded-For` (这是最通用的标准)。
### 2. 生成文件 (`internal/types/types.go`)
- 手动同步修改 `DeviceLoginRequest` 中的 Tag。
- 变为: `IP string header:"X-Forwarded-For"`
### 3. (可选增强) 业务逻辑 (`internal/logic/auth/deviceLoginLogic.go`)
- 由于 go-zero 的绑定机制比较“死”,如果 Tag 没取到值,就是空的。Logic 层拿到空字符串也没办法再去 Context 捞(除非 Context 里存了 request)。
- 暂时只做 Tag 修改,因为这是最根本原因。
## 验证
- 检查代码变更。
- (无法直接测试 IP 获取,依赖用户部署验证)。
## 任务拆分
1. 修改 `apis/auth/auth.api`
2. 修改 `internal/types/types.go`