# IP限制机制

<cite>
**本文档引用文件**  
- [v_1_restrict_ip_record.go](file://internal/dao/v_1_restrict_ip_record.go)
- [v_1_restrict_client_access_record.go](file://internal/dao/v_1_restrict_client_access_record.go)
- [v_1_restrict_ip_order_access.go](file://internal/dao/v_1_restrict_ip_order_access.go)
- [ip_record.go](file://internal/logic/restriction/ip_record.go)
- [device_id_record.go](file://internal/logic/restriction/device_id_record.go)
- [restriction.go](file://internal/service/restriction.go)
- [restriction_v1_check_ip_allowed.go](file://internal/controller/restriction/restriction_v1_check_ip_allowed.go)
- [restriction_v1_block_order.go](file://internal/controller/restriction/restriction_v1_block_order.go)
- [v_1_restrict_ip_record.go](file://internal/model/entity/v_1_restrict_ip_record.go)
- [v_1_restrict_client_access_record.go](file://internal/model/entity/v_1_restrict_client_access_record.go)
- [v_1_restrict_ip_order_access.go](file://internal/model/entity/v_1_restrict_ip_order_access.go)
</cite>

## 目录
1. [简介](#简介)
2. [IP记录存储结构](#ip记录存储结构)
3. [黑白名单管理机制](#黑白名单管理机制)
4. [访问控制策略](#访问控制策略)
5. [配置方法与生效流程](#配置方法与生效流程)
6. [缓存机制与查询优化](#缓存机制与查询优化)
7. [查询接口说明](#查询接口说明)
8. [最佳实践与使用场景](#最佳实践与使用场景)
9. [与其他安全机制的集成](#与其他安全机制的集成)

## 简介

kami_backend系统的IP限制机制是一套完整的访问控制体系，用于防止恶意爬虫、异常登录等安全威胁。该机制通过记录客户端IP地址、设备信息和访问行为，结合黑白名单策略和区域限制，实现精细化的访问控制。系统支持基于卡密、设备ID、IP地址和代理使用情况的多维度限制，并与商户部署策略深度集成，提供灵活的安全防护能力。

**Section sources**
- [restriction_v1_check_ip_allowed.go](file://internal/controller/restriction/restriction_v1_check_ip_allowed.go#L1-L70)
- [restriction.go](file://internal/service/restriction.go#L1-L67)

## IP记录存储结构

IP限制机制采用三层数据模型来存储和管理IP相关信息：

1. **IP基础记录表** (`restrict_ip_record`)：存储IP地址的基本信息
   - IP地址
   - 所在省份/地区
   - 是否为公共IP
   - 原始地理位置数据
   - 创建和更新时间戳

2. **客户端访问记录表** (`restrict_client_access_record`)：存储设备级别的访问信息
   - 访问ID（设备ID）
   - 设备型号
   - 用户代理（User Agent）
   - 是否使用代理

3. **IP订单访问关联表** (`restrict_ip_order_access`)：记录IP与订单的访问关系
   - 关联IP记录ID
   - 订单号
   - 卡密
   - 限制状态
   - 限制策略
   - 设备ID

当系统接收到新的IP访问时，会自动调用`GetOrSetIPRecord`方法检查并创建IP记录。对于公网IP，系统会通过外部服务获取其地理位置信息并存储在`RawData`字段中。

```mermaid
erDiagram
restrict_ip_record {
uint id PK
string ip UK
string ip_province
bool is_public
string raw_data
datetime created_at
datetime updated_at
datetime deleted_at
}
restrict_client_access_record {
uint id PK
string visitor_id UK
string device_model
string user_agent
bool is_use_proxy
datetime created_at
datetime updated_at
datetime deleted_at
}
restrict_ip_order_access {
uint id PK
int restrict_ip_id FK
string order_no
string card_pass
string ip
int status
string restrict_strategy
string device_id
datetime created_at
datetime updated_at
datetime deleted_at
}
restrict_ip_record ||--o{ restrict_ip_order_access : "被限制"
restrict_client_access_record ||--o{ restrict_ip_order_access : "关联"
```

**Diagram sources**
- [v_1_restrict_ip_record.go](file://internal/model/entity/v_1_restrict_ip_record.go#L11-L20)
- [v_1_restrict_client_access_record.go](file://internal/model/entity/v_1_restrict_client_access_record.go#L11-L20)
- [v_1_restrict_ip_order_access.go](file://internal/model/entity/v_1_restrict_ip_order_access.go#L11-L23)

**Section sources**
- [v_1_restrict_ip_record.go](file://internal/dao/v_1_restrict_ip_record.go#L21-L23)
- [v_1_restrict_client_access_record.go](file://internal/dao/v_1_restrict_client_access_record.go#L21-L23)
- [v_1_restrict_ip_order_access.go](file://internal/dao/v_1_restrict_ip_order_access.go#L21-L23)

## 黑白名单管理机制

IP限制机制实现了基于多维度的黑白名单管理，支持以下几种限制类型：

1. **卡密限制**：当某个卡密被标记为受限时，所有使用该卡密的请求都将被阻止
2. **设备限制**：特定设备ID被禁止访问系统
3. **IP限制**：特定IP地址被加入黑名单
4. **代理限制**：检测到使用代理的请求将被阻止
5. **内网IP限制**：可选择是否限制内网IP访问
6. **区域限制**：仅允许或禁止特定省份/地区的访问

系统通过`IsRestrictExistByCardPass`、`IsRestrictDevice`、`IsRestrictExistByIP`等方法检查各种限制条件的存在。当检测到违规行为时，系统会自动将相关信息记录到`restrict_ip_order_access`表中，并设置相应的限制状态。

```mermaid
flowchart TD
A[新请求到达] --> B{检查卡密限制?}
B --> |是| C{卡密已被限制?}
C --> |是| D[拒绝访问]
C --> |否| E{检查设备限制?}
B --> |否| E
E --> |是| F{设备已被限制?}
F --> |是| D
F --> |否| G{检查代理使用?}
E --> |否| G
G --> |是| H{使用代理?}
H --> |是| D
H --> |否| I{检查IP限制?}
G --> |否| I
I --> |是| J{IP已被限制?}
J --> |是| D
J --> |否| K[允许访问]
I --> |否| K
```

**Diagram sources**
- [restriction.go](file://internal/service/restriction.go#L35-L65)
- [restriction_v1_check_ip_allowed.go](file://internal/controller/restriction/restriction_v1_check_ip_allowed.go#L1-L70)

**Section sources**
- [restriction.go](file://internal/service/restriction.go#L35-L65)
- [restriction_v1_check_ip_allowed.go](file://internal/controller/restriction/restriction_v1_check_ip_allowed.go#L1-L70)

## 访问控制策略

访问控制策略由商户部署配置决定，系统在处理每个请求时都会根据预设策略进行判断。控制流程如下：

1. 系统首先获取当前商户部署的限制策略
2. 按照优先级依次检查各项限制条件
3. 任何一项限制条件触发都将导致访问被拒绝
4. 如果所有限制条件都未触发，则允许访问

策略检查的优先级顺序为：
1. 卡密限制
2. 设备限制
3. 代理使用检测
4. IP限制
5. 内网IP特殊处理
6. 区域限制

对于内网IP，系统提供了特殊的处理逻辑：如果策略中未启用内网IP限制，则自动允许所有内网IP访问，这有助于开发和测试环境的便利性。

```mermaid
sequenceDiagram
participant Client as 客户端
participant Controller as 控制器
participant Service as 限制服务
participant DB as 数据库
Client->>Controller : 发送请求(IP,设备ID,卡密)
Controller->>Service : 获取商户限制策略
Service-->>Controller : 返回策略
Controller->>Service : 检查卡密限制
Service-->>Controller : 检查结果
alt 卡密受限
Controller->>Client : 拒绝访问
else
Controller->>Service : 检查设备限制
Service-->>Controller : 检查结果
alt 设备受限
Controller->>Client : 拒绝访问
else
Controller->>Service : 检查代理使用
Service-->>Controller : 检查结果
alt 使用代理
Controller->>Client : 拒绝访问
else
Controller->>Service : 检查IP限制
Service-->>Controller : 检查结果
alt IP受限
Controller->>Client : 拒绝访问
else
Controller->>Client : 允许访问
end
end
end
end
Controller->>Service : 记录限制结果
```

**Diagram sources**
- [restriction_v1_check_ip_allowed.go](file://internal/controller/restriction/restriction_v1_check_ip_allowed.go#L1-L70)
- [restriction.go](file://internal/service/restriction.go#L35-L65)

**Section sources**
- [restriction_v1_check_ip_allowed.go](file://internal/controller/restriction/restriction_v1_check_ip_allowed.go#L1-L70)

## 配置方法与生效流程

### 配置方法

IP限制的配置主要通过商户部署策略进行，包含以下可配置项：

- `IsRestrictCardPass`: 是否启用卡密限制
- `IsRestrictDevice`: 是否启用设备限制
- `IsRestrictAgent`: 是否启用代理检测
- `IsRestrictIp`: 是否启用IP限制
- `IsRestrictInternalIp`: 是否限制内网IP
- `RestrictArea`: 允许访问的省份/地区列表

### 生效流程

1. **请求接收**：系统接收到包含IP、设备ID、卡密等信息的请求
2. **策略获取**：从商户部署配置中获取当前的限制策略
3. **逐项检查**：按照预设顺序检查各项限制条件
4. **结果记录**：无论允许或拒绝，都将结果记录到数据库
5. **响应返回**：向客户端返回访问结果

系统使用事务性操作确保数据一致性，在检查过程中如果发现需要限制的情况，会立即终止后续检查并返回拒绝结果。

```mermaid
flowchart TD
A[接收请求] --> B[获取商户策略]
B --> C[检查卡密限制]
C --> D{卡密受限?}
D --> |是| E[记录拒绝]
D --> |否| F[检查设备限制]
F --> G{设备受限?}
G --> |是| E
G --> |否| H[检查代理使用]
H --> I{使用代理?}
I --> |是| E
I --> |否| J[检查IP限制]
J --> K{IP受限?}
K --> |是| E
K --> |否| L[检查内网IP]
L --> M{内网IP且不禁用?}
M --> |是| N[记录允许]
M --> |否| O[检查区域限制]
O --> P{在允许区域?}
P --> |是| N
P --> |否| E
E --> Q[返回拒绝]
N --> R[返回允许]
```

**Section sources**
- [restriction_v1_check_ip_allowed.go](file://internal/controller/restriction/restriction_v1_check_ip_allowed.go#L1-L70)
- [restriction.go](file://internal/service/restriction.go#L35-L65)

## 缓存机制与查询优化

### 缓存机制

系统虽然没有显式的缓存层，但通过以下方式实现高效的查询性能：

1. **数据库索引优化**：在关键字段上建立索引，包括IP地址、设备ID、卡密等
2. **连接池管理**：使用数据库连接池减少连接开销
3. **对象复用**：通过GoFrame框架的ORM功能复用数据库查询对象

### 查询优化

1. **IP记录查询优化**：
   - 使用`GetOrSetIPRecord`方法实现查询和创建的一体化
   - 对已存在的IP记录直接返回，避免重复查询
   - 对公网IP才进行地理位置查询，减少外部服务调用

2. **设备关联查询优化**：
   - 使用会话ID（SessionId）批量关联IP和设备信息
   - 通过事务确保数据一致性
   - 提供`CheckIsDeviceUseProxy`方法快速判断代理使用情况

3. **批量查询支持**：
   - 提供`GetRestrictRecordByCardPass`和`GetRestrictRecordByIP`方法支持按卡密或IP批量查询限制记录
   - 使用ORM的Scan功能直接映射到结构体，减少数据转换开销

系统通过合理的数据库设计和查询逻辑，确保在大规模IP数据情况下仍能保持快速的查询性能。

**Section sources**
- [ip_record.go](file://internal/logic/restriction/ip_record.go#L1-L55)
- [device_id_record.go](file://internal/logic/restriction/device_id_record.go#L1-L114)
- [restriction.go](file://internal/service/restriction.go#L35-L65)

## 查询接口说明

系统提供了多个查询接口用于IP限制相关的数据检索：

### 主要查询接口

1. **IP记录查询**
   - 方法：`GetOrSetIPRecord`
   - 功能：获取或创建IP记录
   - 参数：IP地址
   - 返回：IP记录信息及地理位置数据

2. **限制存在性检查**
   - 方法：`IsRestrictExistByCardPass`
   - 功能：检查指定卡密是否存在限制记录
   - 参数：卡密
   - 返回：布尔值

   - 方法：`IsRestrictExistByIP`
   - 功能：检查指定IP是否存在限制记录
   - 参数：IP地址
   - 返回：布尔值

3. **记录批量查询**
   - 方法：`GetRestrictRecordByCardPass`
   - 功能：获取指定卡密的所有限制记录
   - 参数：卡密
   - 返回：限制记录列表

   - 方法：`GetRestrictRecordByIP`
   - 功能：获取指定IP的所有限制记录
   - 参数：IP地址
   - 返回：包含IP记录的限制记录列表

4. **区域检查**
   - 方法：`CheckIPIsAllowed`
   - 功能：检查IP是否在允许的区域内
   - 参数：IP地址、允许区域列表
   - 返回：是否允许访问

这些接口通过服务层统一暴露，控制器可以直接调用，确保了接口的一致性和安全性。

**Section sources**
- [restriction.go](file://internal/service/restriction.go#L35-L65)
- [ip_record.go](file://internal/logic/restriction/ip_record.go#L1-L55)

## 最佳实践与使用场景

### 最佳实践

1. **合理配置限制策略**：根据业务需求选择合适的限制维度，避免过度限制影响正常用户
2. **定期清理过期记录**：设置适当的数据保留策略，定期清理不再需要的限制记录
3. **监控限制触发情况**：建立监控系统，及时发现异常的限制触发模式
4. **灰度发布新策略**：新限制策略应先在小范围用户中测试，确认无误后再全面推广

### 使用场景示例

#### 防止恶意爬虫

通过启用IP限制和代理检测，可以有效识别和阻止爬虫行为：
- 检测到使用代理的请求自动限制
- 对短时间内频繁访问的IP进行限制
- 结合设备ID识别伪装的爬虫

#### 限制异常登录

保护用户账户安全：
- 对多次登录失败的IP进行临时限制
- 检测异地登录行为，要求额外验证
- 限制同一账号在多设备上的并发登录

#### 区域访问控制

满足业务合规要求：
- 仅允许特定省份的用户访问服务
- 阻止来自高风险地区的访问
- 为不同地区用户提供差异化服务

#### 卡密安全保护

防止卡密滥用：
- 一个卡密只能在有限的设备上使用
- 检测卡密的异常使用模式
- 对疑似泄露的卡密立即限制

这些场景展示了IP限制机制在实际业务中的灵活应用，通过组合不同的限制维度，可以构建多层次的安全防护体系。

**Section sources**
- [restriction_v1_check_ip_allowed.go](file://internal/controller/restriction/restriction_v1_check_ip_allowed.go#L1-L70)
- [restriction.go](file://internal/service/restriction.go#L35-L65)

## 与其他安全机制的集成

IP限制机制与系统的其他安全组件紧密集成，形成完整的安全防护体系：

### 与登录频率限制的集成

1. **协同工作模式**：
   - 登录频率限制检测到异常登录行为
   - 触发IP限制机制将相关IP加入黑名单
   - 后续来自该IP的所有请求都被阻止

2. **数据共享**：
   - 共用设备ID和IP地址信息
   - 登录日志作为IP限制的决策依据
   - 限制结果反馈给登录系统用于风险评估

### 与商户部署策略的集成

1. **策略驱动**：
   - 商户可以自定义IP限制策略
   - 不同商户可以有不同的安全要求
   - 策略变更实时生效

2. **差异化服务**：
   - 高风险商户启用更严格的限制
   - 信任商户可以放宽某些限制条件
   - 根据商户等级动态调整安全策略

### 与设备指纹的集成

1. **设备识别**：
   - 结合User Agent和设备型号生成设备指纹
   - 识别伪装的设备和浏览器
   - 检测自动化工具的使用

2. **行为分析**：
   - 跟踪设备的访问模式
   - 识别异常的行为特征
   - 提前预警潜在的安全威胁

这种深度集成使得IP限制不仅仅是简单的IP黑名单，而是成为智能安全决策系统的重要组成部分，能够根据上下文信息做出更精准的访问控制决策。

**Section sources**
- [restriction_v1_check_ip_allowed.go](file://internal/controller/restriction/restriction_v1_check_ip_allowed.go#L1-L70)
- [restriction.go](file://internal/service/restriction.go#L35-L65)
- [device_id_record.go](file://internal/logic/restriction/device_id_record.go#L1-L114)