docs(readme): 重构README并补充详细文档内容
This commit is contained in:
715
.qoder/repowiki/zh/content/故障排除/加密解密问题.md
Normal file
715
.qoder/repowiki/zh/content/故障排除/加密解密问题.md
Normal file
@@ -0,0 +1,715 @@
|
||||
# 加密解密问题
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [TsCrypto.js](file://src/utils/TsCrypto.js)
|
||||
- [TsSM4.js](file://src/utils/TsSM4.js)
|
||||
- [TsGlobalConfig.js](file://src/utils/TsGlobalConfig.js)
|
||||
- [TsHttpUtil.js](file://src/https/TsHttpUtil.js)
|
||||
- [TsStorage.js](file://src/utils/TsStorage.js)
|
||||
- [package.json](file://package.json)
|
||||
- [index.js](file://index.js)
|
||||
- [README.md](file://README.md)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构概览](#架构概览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排除指南](#故障排除指南)
|
||||
9. [结论](#结论)
|
||||
|
||||
## 简介
|
||||
|
||||
本指南专注于该代码库中的加密解密功能,特别是SM4算法的实现和使用。该工具包提供了完整的加密解密解决方案,包括密钥管理、数据加密、HTTP请求加密传输等功能。本文档将详细说明如何诊断和解决加密解密过程中可能遇到的各种问题。
|
||||
|
||||
## 项目结构
|
||||
|
||||
该项目采用模块化设计,主要包含以下核心模块:
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "核心模块"
|
||||
Crypto[TsCrypto<br/>加密器]
|
||||
SM4[TsSM4<br/>SM4算法实现]
|
||||
HttpUtil[TsHttpUtil<br/>HTTP工具]
|
||||
end
|
||||
subgraph "配置管理"
|
||||
GlobalConfig[TsGlobalConfig<br/>全局配置]
|
||||
Storage[TsStorage<br/>本地存储]
|
||||
end
|
||||
subgraph "工具函数"
|
||||
Common[TsCommon<br/>通用工具]
|
||||
end
|
||||
Crypto --> SM4
|
||||
HttpUtil --> Crypto
|
||||
HttpUtil --> GlobalConfig
|
||||
HttpUtil --> Storage
|
||||
Crypto --> GlobalConfig
|
||||
Storage --> Common
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [index.js:1-16](file://index.js#L1-L16)
|
||||
- [package.json:19-22](file://package.json#L19-L22)
|
||||
|
||||
**章节来源**
|
||||
- [index.js:1-16](file://index.js#L1-L16)
|
||||
- [package.json:1-24](file://package.json#L1-L24)
|
||||
|
||||
## 核心组件
|
||||
|
||||
### 加密器 (TsCrypto)
|
||||
|
||||
加密器是整个加密系统的核心,负责协调SM4算法和密钥管理:
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class TsCrypto {
|
||||
-sm4 : SM4
|
||||
+constructor()
|
||||
+encrypt(content) : String
|
||||
+decrypt(base64) : String
|
||||
}
|
||||
class SM4 {
|
||||
-key : Uint8Array
|
||||
-iv : Uint8Array
|
||||
-mode : String
|
||||
-cipherType : String
|
||||
-encryptRoundKeys : Uint32Array
|
||||
-decryptRoundKeys : Uint32Array
|
||||
+constructor(config)
|
||||
+encrypt(plaintext) : String
|
||||
+decrypt(ciphertext) : String
|
||||
}
|
||||
TsCrypto --> SM4 : 使用
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsCrypto.js:5-34](file://src/utils/TsCrypto.js#L5-L34)
|
||||
- [TsSM4.js:96-156](file://src/utils/TsSM4.js#L96-L156)
|
||||
|
||||
### HTTP加密传输
|
||||
|
||||
HTTP工具实现了端到端的加密传输机制:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as 客户端
|
||||
participant HttpUtil as HTTP工具
|
||||
participant Crypto as 加密器
|
||||
participant Server as 服务器
|
||||
Client->>HttpUtil : 发送请求(启用加密)
|
||||
HttpUtil->>Crypto : encrypt(JSON.stringify(data))
|
||||
Crypto->>Crypto : SM4加密
|
||||
Crypto-->>HttpUtil : 返回加密数据
|
||||
HttpUtil->>Server : POST /api (encryptData)
|
||||
Server->>Server : 解密响应数据
|
||||
Server-->>HttpUtil : 返回加密响应
|
||||
HttpUtil->>Crypto : decrypt(response.data)
|
||||
Crypto-->>HttpUtil : 返回明文数据
|
||||
HttpUtil-->>Client : 返回解析后的数据
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsHttpUtil.js:82-86](file://src/https/TsHttpUtil.js#L82-L86)
|
||||
- [TsHttpUtil.js:119-122](file://src/https/TsHttpUtil.js#L119-L122)
|
||||
|
||||
**章节来源**
|
||||
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
|
||||
- [TsSM4.js:96-456](file://src/utils/TsSM4.js#L96-L456)
|
||||
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
|
||||
|
||||
## 架构概览
|
||||
|
||||
该系统的加密架构遵循分层设计原则:
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph "应用层"
|
||||
App[业务应用]
|
||||
end
|
||||
subgraph "HTTP层"
|
||||
HttpUtil[HTTP工具]
|
||||
EncryptSwitch[加密开关]
|
||||
end
|
||||
subgraph "加密层"
|
||||
Crypto[加密器]
|
||||
SM4[SM4算法]
|
||||
Padding[填充算法]
|
||||
end
|
||||
subgraph "配置层"
|
||||
Config[全局配置]
|
||||
KeyStore[密钥存储]
|
||||
end
|
||||
subgraph "传输层"
|
||||
Network[网络传输]
|
||||
Base64[Base64编码]
|
||||
end
|
||||
App --> HttpUtil
|
||||
HttpUtil --> EncryptSwitch
|
||||
EncryptSwitch --> Crypto
|
||||
Crypto --> SM4
|
||||
SM4 --> Padding
|
||||
Crypto --> Config
|
||||
Config --> KeyStore
|
||||
SM4 --> Base64
|
||||
Base64 --> Network
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsHttpUtil.js:82-86](file://src/https/TsHttpUtil.js#L82-L86)
|
||||
- [TsCrypto.js:8-12](file://src/utils/TsCrypto.js#L8-L12)
|
||||
- [TsSM4.js:287-312](file://src/utils/TsSM4.js#L287-L312)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### SM4算法实现
|
||||
|
||||
SM4是中国国家密码标准的对称加密算法,具有以下特点:
|
||||
|
||||
#### 核心算法特性
|
||||
- **块大小**: 128位 (16字节)
|
||||
- **密钥长度**: 128位 (16字节)
|
||||
- **支持模式**: ECB和CBC两种工作模式
|
||||
- **填充方式**: PKCS#7填充
|
||||
- **输出格式**: Base64编码
|
||||
|
||||
#### 关键实现细节
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始加密]) --> Convert["转换字符串为UTF-8字节数组"]
|
||||
Convert --> Pad["执行PKCS#7填充"]
|
||||
Pad --> Mode{"选择加密模式"}
|
||||
Mode --> |CBC| CBCInit["初始化IV链"]
|
||||
Mode --> |ECB| ECBInit["直接处理块"]
|
||||
CBCInit --> BlockLoop["遍历每个16字节块"]
|
||||
ECBInit --> BlockLoop
|
||||
BlockLoop --> XOR{"CBC模式需要XOR"}
|
||||
XOR --> |是| XORCalc["与前一块结果XOR"]
|
||||
XOR --> |否| DirectCrypt["直接加密"]
|
||||
XORCalc --> SM4Crypt["SM4算法加密"]
|
||||
DirectCrypt --> SM4Crypt
|
||||
SM4Crypt --> Output{"输出格式"}
|
||||
Output --> |Base64| Base64Encode["Base64编码"]
|
||||
Output --> |Text| TextEncode["UTF-8编码"]
|
||||
Base64Encode --> End([完成])
|
||||
TextEncode --> End
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387)
|
||||
- [TsSM4.js:287-312](file://src/utils/TsSM4.js#L287-L312)
|
||||
|
||||
**章节来源**
|
||||
- [TsSM4.js:96-456](file://src/utils/TsSM4.js#L96-L456)
|
||||
|
||||
### 加密器配置
|
||||
|
||||
加密器通过全局配置管理密钥和加密参数:
|
||||
|
||||
#### 配置参数说明
|
||||
|
||||
| 参数名 | 类型 | 必需 | 默认值 | 描述 |
|
||||
|--------|------|------|--------|------|
|
||||
| base64Key | String | 是 | WmdUzPJXbngVNiaSsQrihg== | Base64编码的16字节密钥 |
|
||||
| mode | String | 否 | ecb | 加密模式 (ecb/cbc) |
|
||||
| cipherType | String | 否 | base64 | 输出格式 (base64/text) |
|
||||
|
||||
**章节来源**
|
||||
- [TsCrypto.js:7-13](file://src/utils/TsCrypto.js#L7-L13)
|
||||
- [TsGlobalConfig.js:5-13](file://src/utils/TsGlobalConfig.js#L5-L13)
|
||||
|
||||
### HTTP加密传输机制
|
||||
|
||||
HTTP工具实现了透明的加密传输:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant App as 应用
|
||||
participant Storage as 存储
|
||||
participant HttpUtil as HTTP工具
|
||||
participant Crypto as 加密器
|
||||
participant Server as 服务器
|
||||
App->>Storage : getEncryptBody()
|
||||
Storage-->>App : true/false
|
||||
App->>HttpUtil : post(url, data)
|
||||
HttpUtil->>Storage : 检查加密开关
|
||||
alt 加密开启
|
||||
HttpUtil->>Crypto : encrypt(JSON.stringify(data))
|
||||
Crypto->>Crypto : SM4加密
|
||||
Crypto-->>HttpUtil : 加密结果
|
||||
HttpUtil->>Server : POST encryptData
|
||||
else 加密关闭
|
||||
HttpUtil->>Server : POST 原始数据
|
||||
end
|
||||
Server-->>HttpUtil : 返回响应
|
||||
HttpUtil->>Crypto : decrypt(response.data)
|
||||
Crypto-->>HttpUtil : 明文数据
|
||||
HttpUtil-->>App : 解析后的数据
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsHttpUtil.js:82-86](file://src/https/TsHttpUtil.js#L82-L86)
|
||||
- [TsHttpUtil.js:119-122](file://src/https/TsHttpUtil.js#L119-L122)
|
||||
|
||||
**章节来源**
|
||||
- [TsHttpUtil.js:50-91](file://src/https/TsHttpUtil.js#L50-L91)
|
||||
- [TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23)
|
||||
|
||||
## 依赖关系分析
|
||||
|
||||
项目依赖关系清晰明确,主要依赖如下:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph "外部依赖"
|
||||
Base64[base64-js@1.5.1]
|
||||
UmiRequest[umi-request@1.4.0]
|
||||
end
|
||||
subgraph "内部模块"
|
||||
TsCrypto[TsCrypto.js]
|
||||
TsSM4[TsSM4.js]
|
||||
TsHttpUtil[TsHttpUtil.js]
|
||||
TsGlobalConfig[TsGlobalConfig.js]
|
||||
TsStorage[TsStorage.js]
|
||||
end
|
||||
Base64 --> TsCrypto
|
||||
Base64 --> TsSM4
|
||||
UmiRequest --> TsHttpUtil
|
||||
TsCrypto --> TsSM4
|
||||
TsHttpUtil --> TsCrypto
|
||||
TsHttpUtil --> TsGlobalConfig
|
||||
TsHttpUtil --> TsStorage
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [package.json:19-22](file://package.json#L19-L22)
|
||||
- [TsCrypto.js:1-3](file://src/utils/TsCrypto.js#L1-L3)
|
||||
|
||||
**章节来源**
|
||||
- [package.json:19-22](file://package.json#L19-L22)
|
||||
|
||||
## 性能考虑
|
||||
|
||||
### 加密性能特征
|
||||
|
||||
1. **算法复杂度**: SM4算法的时间复杂度为O(n),其中n为数据块数量
|
||||
2. **内存使用**: 主要受数据大小影响,每个块16字节
|
||||
3. **CPU消耗**: 对称加密算法,CPU开销相对较小
|
||||
|
||||
### 优化建议
|
||||
|
||||
1. **批量处理**: 对于大量小数据,考虑合并处理以减少开销
|
||||
2. **缓存策略**: 对于重复的加密操作,可以考虑结果缓存
|
||||
3. **异步处理**: 在大数据量场景下使用异步处理避免阻塞
|
||||
|
||||
## 故障排除指南
|
||||
|
||||
### SM4加密失败
|
||||
|
||||
#### 常见错误及解决方案
|
||||
|
||||
**错误1: 密钥长度不正确**
|
||||
- **错误信息**: "key should be a 16 bytes string"
|
||||
- **原因**: 密钥必须是16字节(128位)
|
||||
- **解决方案**:
|
||||
1. 验证密钥长度是否为16字节
|
||||
2. 确认Base64密钥解码后长度为16
|
||||
3. 检查密钥是否被意外截断或修改
|
||||
|
||||
**错误2: IV参数错误**
|
||||
- **错误信息**: "iv error"
|
||||
- **原因**: CBC模式下IV必须存在且长度为16字节
|
||||
- **解决方案**:
|
||||
1. 确保在CBC模式下提供正确的IV
|
||||
2. 验证IV长度为16字节
|
||||
3. 检查IV是否与加密端一致
|
||||
|
||||
**错误3: 数据格式问题**
|
||||
- **错误信息**: 解密时抛出异常
|
||||
- **原因**: 输入数据格式不符合预期
|
||||
- **解决方案**:
|
||||
1. 确认输入数据为正确的Base64字符串
|
||||
2. 验证数据完整性
|
||||
3. 检查是否有额外的空白字符
|
||||
|
||||
#### 排查流程
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始排查]) --> CheckKey["检查密钥配置"]
|
||||
CheckKey --> KeyOK{"密钥有效?"}
|
||||
KeyOK --> |否| FixKey["修复密钥配置"]
|
||||
KeyOK --> |是| CheckMode["检查加密模式"]
|
||||
FixKey --> CheckMode
|
||||
CheckMode --> ModeOK{"模式正确?"}
|
||||
ModeOK --> |否| FixMode["修正加密模式"]
|
||||
ModeOK --> |是| CheckData["验证数据格式"]
|
||||
FixMode --> CheckData
|
||||
CheckData --> DataOK{"数据格式正确?"}
|
||||
DataOK --> |否| FixData["修正数据格式"]
|
||||
DataOK --> |是| TestEncrypt["测试加密功能"]
|
||||
FixData --> TestEncrypt
|
||||
TestEncrypt --> Success{"问题解决?"}
|
||||
Success --> |否| ContactSupport["联系技术支持"]
|
||||
Success --> |是| End([完成])
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsSM4.js:103-122](file://src/utils/TsSM4.js#L103-L122)
|
||||
- [TsSM4.js:345-347](file://src/utils/TsSM4.js#L345-L347)
|
||||
|
||||
### 解密错误
|
||||
|
||||
#### 常见解密问题
|
||||
|
||||
**问题1: 解密结果为空或乱码**
|
||||
- **症状**: 解密后返回空字符串或不可读字符
|
||||
- **可能原因**:
|
||||
1. 密钥不匹配
|
||||
2. 数据在传输过程中被篡改
|
||||
3. 编码格式不一致
|
||||
|
||||
**问题2: 解密抛出异常**
|
||||
- **症状**: 程序直接崩溃
|
||||
- **可能原因**:
|
||||
1. Base64字符串无效
|
||||
2. 数据长度不是16字节的倍数
|
||||
3. 填充数据损坏
|
||||
|
||||
**问题3: 解密速度慢**
|
||||
- **症状**: 解密过程耗时较长
|
||||
- **可能原因**:
|
||||
1. 数据量过大
|
||||
2. 系统资源不足
|
||||
3. 算法实现效率问题
|
||||
|
||||
#### 解决方案
|
||||
|
||||
**步骤1: 验证密钥配置**
|
||||
1. 检查全局配置中的base64Key
|
||||
2. 确认密钥解码后长度为16字节
|
||||
3. 验证密钥与服务器端一致
|
||||
|
||||
**步骤2: 检查数据完整性**
|
||||
1. 验证Base64字符串格式
|
||||
2. 确认数据未被截断
|
||||
3. 检查是否有额外字符
|
||||
|
||||
**步骤3: 测试解密流程**
|
||||
```javascript
|
||||
// 示例测试代码
|
||||
try {
|
||||
const testData = "your_base64_data_here";
|
||||
const decrypted = crypto.decrypt(testData);
|
||||
console.log("解密结果:", decrypted);
|
||||
} catch (error) {
|
||||
console.error("解密失败:", error.message);
|
||||
}
|
||||
```
|
||||
|
||||
### Base64编码问题
|
||||
|
||||
#### 常见Base64问题
|
||||
|
||||
**问题1: 编码后数据长度异常**
|
||||
- **现象**: Base64编码后的数据长度不符合预期
|
||||
- **原因**: 字符串编码问题或数据截断
|
||||
|
||||
**问题2: 解码失败**
|
||||
- **现象**: Base64解码时报错
|
||||
- **原因**: 包含非法字符或格式错误
|
||||
|
||||
**问题3: 中文字符显示异常**
|
||||
- **现象**: 中文字符在Base64中显示为乱码
|
||||
- **原因**: 编码/解码时未使用UTF-8
|
||||
|
||||
#### 排查方法
|
||||
|
||||
**方法1: 验证编码一致性**
|
||||
1. 确保使用UTF-8编码
|
||||
2. 检查Base64字符集
|
||||
3. 验证填充字符处理
|
||||
|
||||
**方法2: 测试编码流程**
|
||||
```javascript
|
||||
// 编码测试
|
||||
const original = "测试数据";
|
||||
const encoded = base64js.fromByteArray(utf8Encode(original));
|
||||
const decoded = utf8Decode(base64js.toByteArray(encoded));
|
||||
|
||||
if (original === decoded) {
|
||||
console.log("编码解码正常");
|
||||
} else {
|
||||
console.log("编码解码异常");
|
||||
}
|
||||
```
|
||||
|
||||
### 密钥配置错误
|
||||
|
||||
#### 配置检查清单
|
||||
|
||||
**检查项1: 密钥格式**
|
||||
- Base64密钥必须为44个字符(16字节)
|
||||
- 不包含任何空白字符
|
||||
- 符合Base64字符集
|
||||
|
||||
**检查项2: 密钥内容**
|
||||
- 确认密钥未被修改
|
||||
- 验证密钥与服务器端一致
|
||||
- 检查是否有特殊字符
|
||||
|
||||
**检查项3: 配置加载**
|
||||
- 确认全局配置正确加载
|
||||
- 验证window.httpConfig设置
|
||||
- 检查配置优先级
|
||||
|
||||
#### 修复步骤
|
||||
|
||||
1. **重新生成密钥**: 使用安全的随机源生成新的16字节密钥
|
||||
2. **更新配置**: 将新密钥设置到全局配置中
|
||||
3. **同步服务器**: 更新服务器端的密钥配置
|
||||
4. **测试验证**: 执行完整的加解密测试
|
||||
|
||||
### 加密模式选择不当
|
||||
|
||||
#### ECB vs CBC模式对比
|
||||
|
||||
| 特性 | ECB模式 | CBC模式 |
|
||||
|------|---------|---------|
|
||||
| 安全性 | 较低,相同明文产生相同密文 | 较高,引入随机性 |
|
||||
| 性能 | 稍快 | 稍慢 |
|
||||
| 实现复杂度 | 简单 | 需要IV |
|
||||
| 适用场景 | 短小、独立的数据 | 一般数据传输 |
|
||||
|
||||
**选择建议**:
|
||||
- **CBC模式**: 推荐用于大多数场景
|
||||
- **ECB模式**: 仅适用于特殊需求或测试
|
||||
|
||||
### 填充算法不匹配
|
||||
|
||||
#### PKCS#7填充规则
|
||||
|
||||
PKCS#7填充确保数据长度为16字节的倍数:
|
||||
- 填充值 = 16 - (明文字节长度 % 16)
|
||||
- 最少填充1字节,最多填充16字节
|
||||
|
||||
**常见问题**:
|
||||
1. 填充长度计算错误
|
||||
2. 填充字节值不正确
|
||||
3. 去填充逻辑错误
|
||||
|
||||
**解决方案**:
|
||||
1. 严格遵循PKCS#7标准
|
||||
2. 验证填充字节的数值
|
||||
3. 确保去填充时正确处理边界情况
|
||||
|
||||
### 加密开关状态检查
|
||||
|
||||
#### 开关状态验证
|
||||
|
||||
**检查点1: 存储状态**
|
||||
```javascript
|
||||
// 检查加密开关状态
|
||||
const encryptStatus = Storage.getEncryptBody();
|
||||
console.log("加密开关状态:", encryptStatus);
|
||||
```
|
||||
|
||||
**检查点2: 请求流程**
|
||||
```javascript
|
||||
// 验证加密请求
|
||||
const options = {
|
||||
method: 'POST',
|
||||
data: {key: 'value'}
|
||||
};
|
||||
|
||||
// 检查是否被加密
|
||||
if (Storage.getEncryptBody()) {
|
||||
console.log("数据将被加密传输");
|
||||
}
|
||||
```
|
||||
|
||||
**检查点3: 响应处理**
|
||||
```javascript
|
||||
// 验证解密响应
|
||||
const response = await HttpUtil.post('/api', data);
|
||||
console.log("响应数据:", response.data);
|
||||
```
|
||||
|
||||
### 密钥存储位置验证
|
||||
|
||||
#### 存储验证方法
|
||||
|
||||
**验证1: 全局配置检查**
|
||||
```javascript
|
||||
const globalConfig = GlobalConfig.getConfig();
|
||||
console.log("当前密钥:", globalConfig.base64Key);
|
||||
```
|
||||
|
||||
**验证2: 环境变量检查**
|
||||
```javascript
|
||||
// 检查运行环境
|
||||
console.log("NODE_ENV:", process.env.NODE_ENV);
|
||||
console.log("浏览器环境:", typeof window !== 'undefined');
|
||||
```
|
||||
|
||||
**验证3: 配置优先级**
|
||||
```javascript
|
||||
// 验证配置覆盖
|
||||
const config = GlobalConfig.getConfig();
|
||||
console.log("最终配置:", config);
|
||||
```
|
||||
|
||||
### 加密数据格式验证
|
||||
|
||||
#### 数据格式检查
|
||||
|
||||
**检查1: 输入数据格式**
|
||||
```javascript
|
||||
// 验证输入数据
|
||||
function validateInput(data) {
|
||||
if (typeof data !== 'object') {
|
||||
throw new Error('输入必须是对象');
|
||||
}
|
||||
|
||||
const jsonStr = JSON.stringify(data);
|
||||
if (jsonStr.length === 0) {
|
||||
throw new Error('输入数据为空');
|
||||
}
|
||||
|
||||
return jsonStr;
|
||||
}
|
||||
```
|
||||
|
||||
**检查2: 输出数据格式**
|
||||
```javascript
|
||||
// 验证输出格式
|
||||
function validateOutput(data) {
|
||||
if (typeof data !== 'string') {
|
||||
throw new Error('输出必须是字符串');
|
||||
}
|
||||
|
||||
// 检查Base64格式
|
||||
const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
|
||||
if (!base64Regex.test(data)) {
|
||||
throw new Error('输出不是有效的Base64格式');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
**检查3: 数据完整性**
|
||||
```javascript
|
||||
// 验证数据完整性
|
||||
function verifyIntegrity(original, decrypted) {
|
||||
return original === decrypted;
|
||||
}
|
||||
```
|
||||
|
||||
### 错误信息解读
|
||||
|
||||
#### 常见错误类型
|
||||
|
||||
**类型1: 配置错误**
|
||||
- **错误**: "key should be a 16 bytes string"
|
||||
- **含义**: 密钥长度不正确
|
||||
- **处理**: 检查密钥配置和Base64解码
|
||||
|
||||
**类型2: 模式错误**
|
||||
- **错误**: "iv error"
|
||||
- **含义**: CBC模式缺少或错误的IV
|
||||
- **处理**: 提供正确的16字节IV
|
||||
|
||||
**类型3: 数据格式错误**
|
||||
- **错误**: 解码异常
|
||||
- **含义**: Base64数据格式不正确
|
||||
- **处理**: 验证数据格式和完整性
|
||||
|
||||
**类型4: 算法错误**
|
||||
- **错误**: 加密/解密失败
|
||||
- **含义**: 算法实现或参数配置问题
|
||||
- **处理**: 检查算法参数和实现
|
||||
|
||||
### 性能问题诊断
|
||||
|
||||
#### 性能监控
|
||||
|
||||
**监控指标**:
|
||||
1. **加密时间**: 单次加密耗时
|
||||
2. **解密时间**: 单次解密耗时
|
||||
3. **内存使用**: 加密过程中的内存占用
|
||||
4. **CPU使用率**: 加密操作的CPU消耗
|
||||
|
||||
**诊断步骤**:
|
||||
1. **基准测试**: 测量不同数据大小下的性能
|
||||
2. **瓶颈识别**: 使用性能分析工具定位瓶颈
|
||||
3. **优化实施**: 根据分析结果进行优化
|
||||
|
||||
#### 优化建议
|
||||
|
||||
**建议1: 批处理优化**
|
||||
```javascript
|
||||
// 批量处理多个数据
|
||||
function batchEncrypt(dataList) {
|
||||
return dataList.map(data => crypto.encrypt(JSON.stringify(data)));
|
||||
}
|
||||
```
|
||||
|
||||
**建议2: 缓存策略**
|
||||
```javascript
|
||||
// 缓存常用数据
|
||||
const cache = new Map();
|
||||
|
||||
function cachedEncrypt(data) {
|
||||
const key = JSON.stringify(data);
|
||||
if (cache.has(key)) {
|
||||
return cache.get(key);
|
||||
}
|
||||
|
||||
const result = crypto.encrypt(JSON.stringify(data));
|
||||
cache.set(key, result);
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
**建议3: 异步处理**
|
||||
```javascript
|
||||
// 异步处理大数据
|
||||
async function asyncEncrypt(data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
try {
|
||||
const result = crypto.encrypt(data);
|
||||
resolve(result);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## 结论
|
||||
|
||||
该加密解密系统提供了完整的SM4加密解决方案,具有以下特点:
|
||||
|
||||
1. **安全性**: 采用国家标准的SM4算法,支持ECB和CBC两种模式
|
||||
2. **易用性**: 提供简单的API接口,支持自动加密传输
|
||||
3. **可配置性**: 支持多种配置选项,满足不同需求
|
||||
4. **可靠性**: 完善的错误处理和验证机制
|
||||
|
||||
在使用过程中,重点关注密钥配置、数据格式、加密模式选择等方面的问题。通过本文档提供的故障排除指南,可以快速定位和解决大部分加密解密相关问题。
|
||||
|
||||
对于生产环境部署,建议:
|
||||
- 使用强随机源生成密钥
|
||||
- 定期轮换密钥
|
||||
- 实施完善的日志记录
|
||||
- 进行定期的安全审计
|
||||
- 建立应急响应机制
|
||||
652
.qoder/repowiki/zh/content/故障排除/存储访问问题.md
Normal file
652
.qoder/repowiki/zh/content/故障排除/存储访问问题.md
Normal file
@@ -0,0 +1,652 @@
|
||||
# 存储访问问题
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [TsStorage.js](file://src/utils/TsStorage.js)
|
||||
- [TsCommon.js](file://src/utils/TsCommon.js)
|
||||
- [TsHttpUtil.js](file://src/https/TsHttpUtil.js)
|
||||
- [TsCrypto.js](file://src/utils/TsCrypto.js)
|
||||
- [TsSM4.js](file://src/utils/TsSM4.js)
|
||||
- [TsGlobalConfig.js](file://src/utils/TsGlobalConfig.js)
|
||||
- [index.js](file://index.js)
|
||||
- [package.json](file://package.json)
|
||||
- [README.md](file://README.md)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构概览](#架构概览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [存储访问故障排除指南](#存储访问故障排除指南)
|
||||
7. [依赖关系分析](#依赖关系分析)
|
||||
8. [性能考虑](#性能考虑)
|
||||
9. [故障排除指南](#故障排除指南)
|
||||
10. [结论](#结论)
|
||||
|
||||
## 简介
|
||||
|
||||
本指南专注于存储访问相关的故障排除,涵盖localStorage访问失败、数据读取错误、存储空间不足、数据格式异常等问题的诊断和解决方法。该工具包提供了完整的本地存储解决方案,包括数据序列化、加密存储、错误处理等功能。
|
||||
|
||||
## 项目结构
|
||||
|
||||
该项目采用模块化设计,主要包含以下核心模块:
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "主入口"
|
||||
Index[index.js]
|
||||
end
|
||||
subgraph "存储模块"
|
||||
Storage[TsStorage.js]
|
||||
Common[TsCommon.js]
|
||||
end
|
||||
subgraph "网络模块"
|
||||
HttpUtil[TsHttpUtil.js]
|
||||
Crypto[TsCrypto.js]
|
||||
SM4[TsSM4.js]
|
||||
Config[TsGlobalConfig.js]
|
||||
end
|
||||
subgraph "外部依赖"
|
||||
UmiRequest[umi-request]
|
||||
Base64[base64-js]
|
||||
end
|
||||
Index --> Storage
|
||||
Index --> HttpUtil
|
||||
Index --> Crypto
|
||||
Index --> Config
|
||||
Storage --> Common
|
||||
HttpUtil --> Storage
|
||||
HttpUtil --> Crypto
|
||||
Crypto --> SM4
|
||||
Crypto --> Config
|
||||
HttpUtil --> UmiRequest
|
||||
Crypto --> Base64
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [index.js:1-16](file://index.js#L1-L16)
|
||||
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
|
||||
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
|
||||
|
||||
**章节来源**
|
||||
- [index.js:1-16](file://index.js#L1-L16)
|
||||
- [package.json:1-24](file://package.json#L1-L24)
|
||||
|
||||
## 核心组件
|
||||
|
||||
### 存储管理器 (TsStorage)
|
||||
|
||||
存储管理器提供了完整的localStorage操作接口,支持数据的保存、读取和用户令牌管理。
|
||||
|
||||
**主要功能特性:**
|
||||
- 数据序列化和反序列化
|
||||
- 用户令牌存储和获取
|
||||
- 加密开关控制
|
||||
- 错误处理和默认值机制
|
||||
|
||||
### 通用工具 (TsCommon)
|
||||
|
||||
提供了基础的JavaScript工具函数,特别是JSON解析和数据验证功能。
|
||||
|
||||
**关键功能:**
|
||||
- 安全的JSON解析
|
||||
- 空值检测
|
||||
- 字符串处理工具
|
||||
|
||||
### 网络请求 (TsHttpUtil)
|
||||
|
||||
集成了存储功能的HTTP客户端,支持自动数据加密和令牌管理。
|
||||
|
||||
**核心特性:**
|
||||
- 自动令牌注入
|
||||
- 条件数据加密
|
||||
- 统一错误处理
|
||||
- 配置化参数处理
|
||||
|
||||
## 架构概览
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as 客户端应用
|
||||
participant Storage as 存储管理器
|
||||
participant Common as 通用工具
|
||||
participant Crypto as 加密模块
|
||||
participant HTTP as HTTP客户端
|
||||
Client->>Storage : 保存数据
|
||||
Storage->>Storage : 序列化数据
|
||||
Storage->>Storage : 写入localStorage
|
||||
Client->>Storage : 读取数据
|
||||
Storage->>Storage : 从localStorage读取
|
||||
Storage->>Common : 解析JSON
|
||||
Common-->>Storage : 返回数据
|
||||
Storage-->>Client : 返回结果
|
||||
Client->>HTTP : 发送请求
|
||||
HTTP->>Storage : 获取用户令牌
|
||||
Storage-->>HTTP : 返回令牌
|
||||
HTTP->>Crypto : 加密数据(可选)
|
||||
Crypto-->>HTTP : 返回加密结果
|
||||
HTTP-->>Client : 返回响应
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsStorage.js:26-43](file://src/utils/TsStorage.js#L26-L43)
|
||||
- [TsCommon.js:29-44](file://src/utils/TsCommon.js#L29-L44)
|
||||
- [TsHttpUtil.js:99-134](file://src/https/TsHttpUtil.js#L99-L134)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 存储组件深度分析
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class TsStorage {
|
||||
+save(key, value) void
|
||||
+get(key, def) string
|
||||
+saveUserToken(token) void
|
||||
+getUserToken() string
|
||||
+saveEncryptBody(bool) void
|
||||
+getEncryptBody() boolean
|
||||
}
|
||||
class TsCommon {
|
||||
+parseJSON(value, def) Object
|
||||
+isEmpty(value) boolean
|
||||
+getParamFormUrl(key, host) string
|
||||
+isDevelopment() boolean
|
||||
}
|
||||
class TsHttpUtil {
|
||||
+req(url, options) Promise
|
||||
+get(url, params, options) Promise
|
||||
+post(url, data, options) Promise
|
||||
+form(url, data, options) Promise
|
||||
}
|
||||
class TsCrypto {
|
||||
+encrypt(content) string
|
||||
+decrypt(base64) string
|
||||
}
|
||||
class TsSM4 {
|
||||
+encrypt(plaintext) string
|
||||
+decrypt(ciphertext) string
|
||||
}
|
||||
TsStorage --> TsCommon : 使用
|
||||
TsHttpUtil --> TsStorage : 依赖
|
||||
TsHttpUtil --> TsCrypto : 使用
|
||||
TsCrypto --> TsSM4 : 使用
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsStorage.js:26-54](file://src/utils/TsStorage.js#L26-L54)
|
||||
- [TsCommon.js:89-97](file://src/utils/TsCommon.js#L89-L97)
|
||||
- [TsHttpUtil.js:168-170](file://src/https/TsHttpUtil.js#L168-L170)
|
||||
- [TsCrypto.js:5-33](file://src/utils/TsCrypto.js#L5-L33)
|
||||
|
||||
**章节来源**
|
||||
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
|
||||
- [TsCommon.js:1-98](file://src/utils/TsCommon.js#L1-L98)
|
||||
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
|
||||
|
||||
## 存储访问故障排除指南
|
||||
|
||||
### 常见存储问题诊断
|
||||
|
||||
#### 1. localStorage 访问失败
|
||||
|
||||
**症状表现:**
|
||||
- 页面加载时报错,提示localStorage不可用
|
||||
- 数据无法保存或读取
|
||||
- 浏览器控制台出现安全错误
|
||||
|
||||
**诊断步骤:**
|
||||
1. 检查浏览器隐私模式设置
|
||||
2. 验证跨域访问权限
|
||||
3. 确认浏览器扩展程序影响
|
||||
4. 检查HTTPS环境要求
|
||||
|
||||
**解决方案:**
|
||||
```javascript
|
||||
// 检查localStorage可用性
|
||||
function checkLocalStorage() {
|
||||
try {
|
||||
const test = 'test';
|
||||
localStorage.setItem(test, test);
|
||||
localStorage.removeItem(test);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 降级方案:使用sessionStorage
|
||||
if (!checkLocalStorage()) {
|
||||
console.warn('localStorage不可用,使用sessionStorage作为替代');
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 数据读取错误
|
||||
|
||||
**症状表现:**
|
||||
- 读取到空值或undefined
|
||||
- JSON解析失败
|
||||
- 数据类型不匹配
|
||||
|
||||
**诊断流程:**
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始诊断]) --> CheckKey["检查键名是否存在"]
|
||||
CheckKey --> KeyExists{"键存在?"}
|
||||
KeyExists --> |否| CreateDefault["创建默认值"]
|
||||
KeyExists --> |是| CheckFormat["检查数据格式"]
|
||||
CheckFormat --> FormatOK{"格式正确?"}
|
||||
FormatOK --> |否| ParseError["JSON解析错误"]
|
||||
FormatOK --> |是| DataType["检查数据类型"]
|
||||
DataType --> TypeOK{"类型匹配?"}
|
||||
TypeOK --> |否| ConvertData["转换数据类型"]
|
||||
TypeOK --> |是| Success["诊断完成"]
|
||||
CreateDefault --> Success
|
||||
ParseError --> FixParse["修复JSON格式"]
|
||||
FixParse --> Success
|
||||
ConvertData --> Success
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsStorage.js:41-43](file://src/utils/TsStorage.js#L41-L43)
|
||||
- [TsCommon.js:34-44](file://src/utils/TsCommon.js#L34-L44)
|
||||
|
||||
**解决方案:**
|
||||
1. 实施默认值机制
|
||||
2. 添加数据类型验证
|
||||
3. 实现错误边界处理
|
||||
|
||||
#### 3. 存储空间不足
|
||||
|
||||
**症状表现:**
|
||||
- 保存数据时报错
|
||||
- 随机数据丢失
|
||||
- 性能明显下降
|
||||
|
||||
**诊断方法:**
|
||||
1. 检查localStorage使用量
|
||||
2. 分析数据增长趋势
|
||||
3. 识别大体积数据项
|
||||
|
||||
**优化策略:**
|
||||
```javascript
|
||||
// 存储容量监控
|
||||
function checkStorageCapacity() {
|
||||
const storage = localStorage;
|
||||
let totalSize = 0;
|
||||
|
||||
for (let key in storage) {
|
||||
if (storage.hasOwnProperty(key)) {
|
||||
totalSize += storage[key].length;
|
||||
}
|
||||
}
|
||||
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
// 清理过期数据
|
||||
function cleanupExpiredData() {
|
||||
const now = Date.now();
|
||||
const maxAge = 7 * 24 * 60 * 60 * 1000; // 7天
|
||||
|
||||
for (let key in localStorage) {
|
||||
if (localStorage.hasOwnProperty(key)) {
|
||||
try {
|
||||
const item = JSON.parse(localStorage.getItem(key));
|
||||
if (item.timestamp && (now - item.timestamp) > maxAge) {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
} catch (e) {
|
||||
// 忽略格式错误的数据
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. 数据格式异常
|
||||
|
||||
**症状表现:**
|
||||
- JSON解析抛出异常
|
||||
- 数据损坏或不完整
|
||||
- 版本升级后数据不兼容
|
||||
|
||||
**诊断步骤:**
|
||||
1. 验证数据完整性
|
||||
2. 检查版本兼容性
|
||||
3. 分析数据结构变化
|
||||
|
||||
**修复方法:**
|
||||
```javascript
|
||||
// 安全的数据读取
|
||||
function safeGet(key, defaultValue = null) {
|
||||
try {
|
||||
const item = localStorage.getItem(key);
|
||||
if (!item) return defaultValue;
|
||||
|
||||
const parsed = JSON.parse(item);
|
||||
return parsed.data || defaultValue;
|
||||
} catch (error) {
|
||||
console.error(`读取存储项 ${key} 失败:`, error);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
// 数据格式验证
|
||||
function validateDataStructure(data) {
|
||||
const requiredFields = ['data'];
|
||||
return requiredFields.every(field => data.hasOwnProperty(field));
|
||||
}
|
||||
```
|
||||
|
||||
### 浏览器兼容性问题
|
||||
|
||||
#### 1. 不同浏览器的差异
|
||||
|
||||
**问题类型:**
|
||||
- Safari隐私模式限制
|
||||
- IE/Edge兼容性问题
|
||||
- 移动端存储限制
|
||||
|
||||
**解决方案:**
|
||||
```javascript
|
||||
// 跨浏览器兼容性检查
|
||||
function isStorageSupported() {
|
||||
const testKey = '__storage_test__';
|
||||
|
||||
try {
|
||||
if ('localStorage' in window && window['localStorage'] !== null) {
|
||||
localStorage.setItem(testKey, testKey);
|
||||
localStorage.removeItem(testKey);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 功能检测而非浏览器检测
|
||||
function getStorageImplementation() {
|
||||
if (isStorageSupported()) {
|
||||
return localStorage;
|
||||
} else if (typeof sessionStorage !== 'undefined') {
|
||||
return sessionStorage;
|
||||
} else {
|
||||
// 无存储支持,使用内存存储
|
||||
return createMemoryStorage();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 存储权限限制
|
||||
|
||||
**常见场景:**
|
||||
- 第三方Cookie限制
|
||||
- HTTPS环境要求
|
||||
- 用户隐私设置
|
||||
|
||||
**处理策略:**
|
||||
```javascript
|
||||
// 权限检查和降级
|
||||
function handleStoragePermissions() {
|
||||
const permissions = {
|
||||
localStorage: false,
|
||||
sessionStorage: false,
|
||||
cookies: false
|
||||
};
|
||||
|
||||
// 检查localStorage
|
||||
try {
|
||||
localStorage.setItem('permission_test', 'test');
|
||||
localStorage.removeItem('permission_test');
|
||||
permissions.localStorage = true;
|
||||
} catch (e) {
|
||||
permissions.localStorage = false;
|
||||
}
|
||||
|
||||
// 检查cookies
|
||||
try {
|
||||
document.cookie = 'permission_test=test';
|
||||
permissions.cookies = true;
|
||||
} catch (e) {
|
||||
permissions.cookies = false;
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
```
|
||||
|
||||
### 数据序列化失败
|
||||
|
||||
#### 1. JSON序列化问题
|
||||
|
||||
**常见原因:**
|
||||
- 循环引用
|
||||
- 函数和undefined
|
||||
- 复杂对象类型
|
||||
|
||||
**诊断方法:**
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([序列化开始]) --> CheckCircular["检查循环引用"]
|
||||
CheckCircular --> HasCircular{"存在循环引用?"}
|
||||
HasCircular --> |是| RemoveCircular["移除循环引用"]
|
||||
HasCircular --> |否| CheckTypes["检查数据类型"]
|
||||
CheckTypes --> HasInvalid{"包含无效类型?"}
|
||||
HasInvalid --> |是| FilterInvalid["过滤无效类型"]
|
||||
HasInvalid --> |否| SafeStringify["安全字符串化"]
|
||||
RemoveCircular --> SafeStringify
|
||||
FilterInvalid --> SafeStringify
|
||||
SafeStringify --> Complete["序列化完成"]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsStorage.js:31-33](file://src/utils/TsStorage.js#L31-L33)
|
||||
|
||||
**解决方案:**
|
||||
```javascript
|
||||
// 安全的JSON序列化
|
||||
function safeStringify(obj) {
|
||||
const seen = new WeakSet();
|
||||
|
||||
return JSON.stringify(obj, (key, value) => {
|
||||
if (typeof value === "object" && value !== null) {
|
||||
if (seen.has(value)) {
|
||||
return "[Circular Reference]";
|
||||
}
|
||||
seen.add(value);
|
||||
}
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
// 自定义序列化器
|
||||
function customSerializer(data) {
|
||||
return {
|
||||
data: data,
|
||||
timestamp: Date.now(),
|
||||
version: "1.0"
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## 依赖关系分析
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph "核心依赖"
|
||||
A[umi-request] --> B[TsHttpUtil]
|
||||
C[base64-js] --> D[TsCrypto]
|
||||
end
|
||||
subgraph "内部模块"
|
||||
E[TsStorage] --> F[TsCommon]
|
||||
B --> E
|
||||
B --> G[TsCrypto]
|
||||
G --> H[TsSM4]
|
||||
G --> I[TsGlobalConfig]
|
||||
end
|
||||
J[index.js] --> E
|
||||
J --> B
|
||||
J --> G
|
||||
J --> I
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [package.json:19-22](file://package.json#L19-L22)
|
||||
- [index.js:1-16](file://index.js#L1-L16)
|
||||
|
||||
**章节来源**
|
||||
- [package.json:1-24](file://package.json#L1-L24)
|
||||
- [index.js:1-16](file://index.js#L1-L16)
|
||||
|
||||
## 性能考虑
|
||||
|
||||
### 存储性能优化
|
||||
|
||||
1. **批量操作优化**
|
||||
- 合并多个存储操作
|
||||
- 使用事务性操作
|
||||
- 避免频繁的读写
|
||||
|
||||
2. **数据压缩**
|
||||
- 对大对象进行压缩
|
||||
- 实现增量更新
|
||||
- 使用索引优化查询
|
||||
|
||||
3. **缓存策略**
|
||||
- 实现内存缓存
|
||||
- 设置合理的过期时间
|
||||
- 支持LRU淘汰算法
|
||||
|
||||
### 数据迁移最佳实践
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始迁移]) --> CheckVersion["检查当前版本"]
|
||||
CheckVersion --> VersionOK{"版本兼容?"}
|
||||
VersionOK --> |是| DirectCopy["直接复制数据"]
|
||||
VersionOK --> |否| TransformData["转换数据格式"]
|
||||
TransformData --> ValidateData["验证数据完整性"]
|
||||
DirectCopy --> ValidateData
|
||||
ValidateData --> MigrationOK{"迁移成功?"}
|
||||
MigrationOK --> |是| UpdateVersion["更新版本号"]
|
||||
MigrationOK --> |否| Rollback["回滚操作"]
|
||||
UpdateVersion --> Complete["迁移完成"]
|
||||
Rollback --> Complete
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsStorage.js:41-43](file://src/utils/TsStorage.js#L41-L43)
|
||||
|
||||
## 故障排除指南
|
||||
|
||||
### 常见错误信息解读
|
||||
|
||||
| 错误类型 | 可能原因 | 解决方案 |
|
||||
|---------|---------|---------|
|
||||
| SecurityError | 跨域访问限制 | 检查域名和协议一致性 |
|
||||
| QuotaExceededError | 存储空间不足 | 清理旧数据或使用压缩 |
|
||||
| InvalidStateError | 存储状态异常 | 重启浏览器或清除缓存 |
|
||||
| TypeError | 数据格式错误 | 实施数据验证和转换 |
|
||||
|
||||
### 诊断工具和方法
|
||||
|
||||
```javascript
|
||||
// 存储状态检查
|
||||
function diagnoseStorage() {
|
||||
const diagnostics = {
|
||||
localStorage: false,
|
||||
sessionStorage: false,
|
||||
quota: 0,
|
||||
items: 0,
|
||||
totalSize: 0
|
||||
};
|
||||
|
||||
// 检查localStorage
|
||||
try {
|
||||
localStorage.setItem('diagnostics', 'test');
|
||||
localStorage.removeItem('diagnostics');
|
||||
diagnostics.localStorage = true;
|
||||
} catch (e) {
|
||||
diagnostics.localStorage = false;
|
||||
}
|
||||
|
||||
// 检查存储配额和使用情况
|
||||
if (navigator.webkitTemporaryStorage) {
|
||||
navigator.webkitTemporaryStorage.queryUsageAndQuota(
|
||||
(usage, quota) => {
|
||||
diagnostics.quota = quota;
|
||||
diagnostics.used = usage;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// 统计存储项数量和大小
|
||||
for (let key in localStorage) {
|
||||
if (localStorage.hasOwnProperty(key)) {
|
||||
diagnostics.items++;
|
||||
diagnostics.totalSize += key.length + localStorage[key].length;
|
||||
}
|
||||
}
|
||||
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
// 数据完整性验证
|
||||
function validateStorageIntegrity() {
|
||||
const errors = [];
|
||||
const keys = Object.keys(localStorage);
|
||||
|
||||
keys.forEach(key => {
|
||||
try {
|
||||
JSON.parse(localStorage.getItem(key));
|
||||
} catch (e) {
|
||||
errors.push({
|
||||
key: key,
|
||||
error: e.message,
|
||||
value: localStorage.getItem(key)
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return errors;
|
||||
}
|
||||
```
|
||||
|
||||
### 最佳实践建议
|
||||
|
||||
1. **错误处理**
|
||||
- 实施全面的try-catch包装
|
||||
- 提供优雅降级机制
|
||||
- 记录详细的错误日志
|
||||
|
||||
2. **数据保护**
|
||||
- 实施数据备份策略
|
||||
- 使用版本控制
|
||||
- 定期数据健康检查
|
||||
|
||||
3. **性能监控**
|
||||
- 监控存储使用率
|
||||
- 跟踪访问模式
|
||||
- 优化热点数据
|
||||
|
||||
**章节来源**
|
||||
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
|
||||
- [TsCommon.js:1-98](file://src/utils/TsCommon.js#L1-L98)
|
||||
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
|
||||
|
||||
## 结论
|
||||
|
||||
存储访问问题的解决需要系统性的方法和完善的监控机制。通过实施本文档提供的诊断流程、故障排除方法和最佳实践,可以有效预防和解决大多数存储相关问题。关键在于建立完善的错误处理机制、实施数据验证和转换、以及持续监控存储状态。
|
||||
|
||||
建议在生产环境中:
|
||||
- 实施多层次的错误处理
|
||||
- 建立存储使用监控
|
||||
- 定期进行数据完整性检查
|
||||
- 制定数据迁移和备份策略
|
||||
|
||||
这样可以确保应用程序的稳定性和可靠性,为用户提供更好的体验。
|
||||
647
.qoder/repowiki/zh/content/故障排除/故障排除.md
Normal file
647
.qoder/repowiki/zh/content/故障排除/故障排除.md
Normal file
@@ -0,0 +1,647 @@
|
||||
# 故障排除
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [README.md](file://README.md)
|
||||
- [package.json](file://package.json)
|
||||
- [index.js](file://index.js)
|
||||
- [TsCommon.js](file://src/utils/TsCommon.js)
|
||||
- [TsCrypto.js](file://src/utils/TsCrypto.js)
|
||||
- [TsSM4.js](file://src/utils/TsSM4.js)
|
||||
- [TsStorage.js](file://src/utils/TsStorage.js)
|
||||
- [TsGlobalConfig.js](file://src/utils/TsGlobalConfig.js)
|
||||
- [TsHttpUtil.js](file://src/https/TsHttpUtil.js)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构概览](#架构概览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排除指南](#故障排除指南)
|
||||
9. [结论](#结论)
|
||||
|
||||
## 简介
|
||||
|
||||
npm-tool 是一个企业级的 JavaScript 工具包,提供了网络请求、数据加密解密、本地存储、通用工具函数等功能。该工具包采用模块化设计,支持多种加密模式和灵活的配置选项,适用于各种 Web 应用场景。
|
||||
|
||||
本指南旨在帮助开发者快速识别和解决使用 npm-tool 时可能遇到的各种问题,提供系统性的调试方法和最佳实践建议。
|
||||
|
||||
## 项目结构
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "项目根目录"
|
||||
A[index.js]
|
||||
B[package.json]
|
||||
C[README.md]
|
||||
end
|
||||
subgraph "src/utils"
|
||||
D[TsCommon.js]
|
||||
E[TsCrypto.js]
|
||||
F[TsSM4.js]
|
||||
G[TsStorage.js]
|
||||
H[TsGlobalConfig.js]
|
||||
end
|
||||
subgraph "src/https"
|
||||
I[TsHttpUtil.js]
|
||||
end
|
||||
A --> D
|
||||
A --> E
|
||||
A --> F
|
||||
A --> G
|
||||
A --> H
|
||||
A --> I
|
||||
E --> F
|
||||
E --> H
|
||||
I --> G
|
||||
I --> D
|
||||
I --> E
|
||||
I --> H
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [index.js:1-16](file://index.js#L1-L16)
|
||||
- [package.json:1-24](file://package.json#L1-L24)
|
||||
|
||||
**章节来源**
|
||||
- [index.js:1-16](file://index.js#L1-L16)
|
||||
- [package.json:1-24](file://package.json#L1-L24)
|
||||
|
||||
## 核心组件
|
||||
|
||||
npm-tool 包含以下核心组件:
|
||||
|
||||
### 网络请求组件 (TsHttpUtil)
|
||||
- 基于 umi-request 的 HTTP 客户端
|
||||
- 支持 GET、POST、表单提交等多种请求方式
|
||||
- 内置加密解密功能
|
||||
- 统一的错误处理机制
|
||||
|
||||
### 数据加密组件 (TsCrypto)
|
||||
- 基于 SM4 算法的对称加密
|
||||
- 支持 ECB 和 CBC 模式
|
||||
- Base64 编码支持
|
||||
|
||||
### 存储组件 (TsStorage)
|
||||
- 基于 localStorage 的数据持久化
|
||||
- 支持用户 Token 管理
|
||||
- 加密开关控制
|
||||
|
||||
### 通用工具组件 (TsCommon)
|
||||
- URL 参数解析
|
||||
- 数据类型判断
|
||||
- JSON 解析工具
|
||||
- 环境检测
|
||||
|
||||
**章节来源**
|
||||
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
|
||||
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
|
||||
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
|
||||
- [TsCommon.js:1-98](file://src/utils/TsCommon.js#L1-L98)
|
||||
|
||||
## 架构概览
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph "应用层"
|
||||
APP[业务应用]
|
||||
end
|
||||
subgraph "HTTP 层"
|
||||
HTTP[TsHttpUtil]
|
||||
CONFIG[TsGlobalConfig]
|
||||
STORAGE[TsStorage]
|
||||
end
|
||||
subgraph "加密层"
|
||||
CRYPTO[TsCrypto]
|
||||
SM4[TsSM4]
|
||||
end
|
||||
subgraph "工具层"
|
||||
COMMON[TsCommon]
|
||||
end
|
||||
subgraph "外部依赖"
|
||||
UMI[umi-request]
|
||||
BASE64[base64-js]
|
||||
end
|
||||
APP --> HTTP
|
||||
HTTP --> CONFIG
|
||||
HTTP --> STORAGE
|
||||
HTTP --> CRYPTO
|
||||
CRYPTO --> SM4
|
||||
HTTP --> COMMON
|
||||
HTTP --> UMI
|
||||
CRYPTO --> BASE64
|
||||
SM4 --> BASE64
|
||||
HTTP -.->|错误处理| APP
|
||||
HTTP -.->|回调函数| APP
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
|
||||
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
|
||||
- [TsSM4.js:1-456](file://src/utils/TsSM4.js#L1-L456)
|
||||
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
|
||||
- [TsGlobalConfig.js:1-34](file://src/utils/TsGlobalConfig.js#L1-L34)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 网络请求组件 (TsHttpUtil)
|
||||
|
||||
#### 请求流程图
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as 应用客户端
|
||||
participant HttpUtil as TsHttpUtil
|
||||
participant Config as TsGlobalConfig
|
||||
participant Storage as TsStorage
|
||||
participant Crypto as TsCrypto
|
||||
participant Request as umi-request
|
||||
participant Server as 服务器
|
||||
Client->>HttpUtil : 发送请求
|
||||
HttpUtil->>Config : 获取全局配置
|
||||
HttpUtil->>Storage : 获取用户Token
|
||||
HttpUtil->>HttpUtil : 处理请求参数
|
||||
alt 需要加密
|
||||
HttpUtil->>Crypto : 加密请求数据
|
||||
Crypto-->>HttpUtil : 返回加密结果
|
||||
end
|
||||
HttpUtil->>Request : 发送HTTP请求
|
||||
Request->>Server : 执行请求
|
||||
Server-->>Request : 返回响应
|
||||
Request-->>HttpUtil : 返回响应数据
|
||||
HttpUtil->>HttpUtil : 处理响应数据
|
||||
alt 响应需要解密
|
||||
HttpUtil->>Crypto : 解密响应数据
|
||||
Crypto-->>HttpUtil : 返回解密结果
|
||||
end
|
||||
HttpUtil-->>Client : 返回处理后的数据
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsHttpUtil.js:99-134](file://src/https/TsHttpUtil.js#L99-L134)
|
||||
- [TsCrypto.js:19-30](file://src/utils/TsCrypto.js#L19-L30)
|
||||
|
||||
#### 错误处理机制
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([请求开始]) --> CheckParams["检查请求参数"]
|
||||
CheckParams --> ParamsValid{"参数有效?"}
|
||||
ParamsValid --> |否| ReturnError["返回参数错误"]
|
||||
ParamsValid --> |是| SendRequest["发送HTTP请求"]
|
||||
SendRequest --> ReceiveResponse["接收响应"]
|
||||
ReceiveResponse --> ResponseType{"响应类型"}
|
||||
ResponseType --> |成功| CheckCode["检查状态码"]
|
||||
ResponseType --> |网络错误| NetworkError["网络错误处理"]
|
||||
ResponseType --> |服务器错误| ServerError["服务器错误处理"]
|
||||
CheckCode --> CodeValid{"状态码200?"}
|
||||
CodeValid --> |是| CheckEncrypt{"需要解密?"}
|
||||
CodeValid --> |否| HttpError["HTTP错误处理"]
|
||||
CheckEncrypt --> |是| DecryptData["解密数据"]
|
||||
CheckEncrypt --> |否| ReturnData["返回数据"]
|
||||
DecryptData --> ParseJSON["解析JSON"]
|
||||
ParseJSON --> ReturnData
|
||||
ReturnError --> End([结束])
|
||||
NetworkError --> End
|
||||
ServerError --> End
|
||||
HttpError --> End
|
||||
ReturnData --> End
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsHttpUtil.js:28-35](file://src/https/TsHttpUtil.js#L28-L35)
|
||||
- [TsHttpUtil.js:117-128](file://src/https/TsHttpUtil.js#L117-L128)
|
||||
|
||||
**章节来源**
|
||||
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
|
||||
|
||||
### 加密解密组件 (TsCrypto)
|
||||
|
||||
#### 加密算法流程
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Input[输入明文] --> ConvertUTF8["转换为UTF-8字节数组"]
|
||||
ConvertUTF8 --> Padding["PKCS7填充"]
|
||||
Padding --> SplitBlocks["分割为16字节块"]
|
||||
SplitBlocks --> ModeSelect{"选择加密模式"}
|
||||
ModeSelect --> |CBC模式| CBCProcess["CBC加密处理"]
|
||||
ModeSelect --> |ECB模式| ECBProcess["ECB加密处理"]
|
||||
CBCProcess --> XORChain["异或链式处理"]
|
||||
XORChain --> BlockCrypt["块加密"]
|
||||
BlockCrypt --> Output[输出密文]
|
||||
ECBProcess --> BlockCrypt
|
||||
BlockCrypt --> Output
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387)
|
||||
- [TsSM4.js:408-452](file://src/utils/TsSM4.js#L408-L452)
|
||||
|
||||
#### 关键配置参数
|
||||
|
||||
| 参数名称 | 类型 | 默认值 | 描述 |
|
||||
|---------|------|--------|------|
|
||||
| keyBuffer | Uint8Array | 从base64Key转换而来 | 16字节密钥缓冲区 |
|
||||
| mode | string | "ecb" | 加密模式 (cbc/ecb) |
|
||||
| cipherType | string | "base64" | 输出类型 (base64/text) |
|
||||
|
||||
**章节来源**
|
||||
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
|
||||
- [TsSM4.js:96-156](file://src/utils/TsSM4.js#L96-L156)
|
||||
|
||||
### 存储组件 (TsStorage)
|
||||
|
||||
#### 数据存储流程
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
SaveRequest[保存请求] --> CheckValue["检查值类型"]
|
||||
CheckValue --> Serialize["序列化JSON"]
|
||||
Serialize --> Store["localStorage存储"]
|
||||
Store --> Success[存储成功]
|
||||
GetRequest[获取请求] --> Load["从localStorage加载"]
|
||||
Load --> ParseJSON["解析JSON"]
|
||||
ParseJSON --> CheckResult{"解析成功?"}
|
||||
CheckResult --> |是| ReturnData["返回数据"]
|
||||
CheckResult --> |否| ReturnDefault["返回默认值"]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsStorage.js:31-43](file://src/utils/TsStorage.js#L31-L43)
|
||||
|
||||
**章节来源**
|
||||
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
|
||||
|
||||
## 依赖关系分析
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph "核心模块"
|
||||
A[index.js]
|
||||
B[TsHttpUtil]
|
||||
C[TsCrypto]
|
||||
D[TsSM4]
|
||||
E[TsStorage]
|
||||
F[TsCommon]
|
||||
G[TsGlobalConfig]
|
||||
end
|
||||
subgraph "外部依赖"
|
||||
H[umi-request]
|
||||
I[base64-js]
|
||||
end
|
||||
A --> B
|
||||
A --> C
|
||||
A --> D
|
||||
A --> E
|
||||
A --> F
|
||||
A --> G
|
||||
B --> C
|
||||
B --> E
|
||||
B --> F
|
||||
B --> G
|
||||
B --> H
|
||||
C --> D
|
||||
C --> G
|
||||
C --> I
|
||||
D --> I
|
||||
E --> F
|
||||
G --> H
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [index.js:1-16](file://index.js#L1-L16)
|
||||
- [package.json:19-22](file://package.json#L19-L22)
|
||||
|
||||
**章节来源**
|
||||
- [package.json:19-22](file://package.json#L19-L22)
|
||||
|
||||
## 性能考虑
|
||||
|
||||
### 网络请求性能优化
|
||||
|
||||
1. **请求缓存策略**
|
||||
- 对于重复的 GET 请求,建议在应用层实现缓存机制
|
||||
- 合理设置请求头以利用浏览器缓存
|
||||
|
||||
2. **批量请求处理**
|
||||
- 对于多个相关的请求,考虑合并为单个请求
|
||||
- 使用并发请求时注意避免过度并发导致的性能问题
|
||||
|
||||
3. **数据传输优化**
|
||||
- 启用压缩传输(gzip/deflate)
|
||||
- 减少不必要的数据传输量
|
||||
|
||||
### 加密性能优化
|
||||
|
||||
1. **加密算法选择**
|
||||
- SM4 算法相对 AES 更快,适合大量数据加密场景
|
||||
- 对于小数据量,加密开销可能超过数据本身大小
|
||||
|
||||
2. **内存管理**
|
||||
- 注意大对象加密时的内存使用情况
|
||||
- 及时释放不再使用的加密对象
|
||||
|
||||
3. **异步处理**
|
||||
- 对于耗时的加密操作,考虑使用 Web Workers
|
||||
- 避免阻塞主线程
|
||||
|
||||
### 存储性能优化
|
||||
|
||||
1. **localStorage 限制**
|
||||
- 单个域名下约 5-10MB 存储空间
|
||||
- 大量数据存储时考虑分片策略
|
||||
|
||||
2. **序列化开销**
|
||||
- 复杂对象的 JSON 序列化可能影响性能
|
||||
- 对频繁读取的数据考虑缓存策略
|
||||
|
||||
## 故障排除指南
|
||||
|
||||
### 网络请求故障排除
|
||||
|
||||
#### 常见错误类型及解决方案
|
||||
|
||||
**1. CORS 跨域问题**
|
||||
- **症状**: 控制台出现跨域错误,请求被阻止
|
||||
- **原因**: 服务器未正确配置 CORS 头部
|
||||
- **解决方案**:
|
||||
- 确认服务器已设置正确的 Access-Control-Allow-Origin
|
||||
- 检查预检请求的处理逻辑
|
||||
- 验证凭据设置 (credentials: 'include')
|
||||
|
||||
**2. 认证失败**
|
||||
- **症状**: HTTP 401 错误,用户无权限
|
||||
- **原因**: Token 过期或无效
|
||||
- **解决方案**:
|
||||
- 检查用户 Token 是否正确存储
|
||||
- 实现 Token 刷新机制
|
||||
- 验证服务器认证配置
|
||||
|
||||
**3. 请求超时**
|
||||
- **症状**: 网络请求长时间无响应
|
||||
- **原因**: 服务器响应慢或网络问题
|
||||
- **解决方案**:
|
||||
- 设置合理的超时时间
|
||||
- 实现重试机制
|
||||
- 检查服务器性能
|
||||
|
||||
**4. 数据格式错误**
|
||||
- **症状**: JSON 解析失败或数据格式不匹配
|
||||
- **原因**: 服务器返回数据格式不符合预期
|
||||
- **解决方案**:
|
||||
- 检查服务器响应格式
|
||||
- 实现数据验证和转换
|
||||
- 添加容错处理
|
||||
|
||||
#### 调试步骤
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Problem[发现网络问题] --> CheckConsole["检查浏览器控制台"]
|
||||
CheckConsole --> VerifyNetwork["验证网络连接"]
|
||||
VerifyNetwork --> TestEndpoint["测试目标端点"]
|
||||
TestEndpoint --> InspectHeaders["检查请求/响应头"]
|
||||
InspectHeaders --> ValidateData["验证数据格式"]
|
||||
ValidateData --> CheckAuth["检查认证信息"]
|
||||
CheckAuth --> ReviewLogs["查看服务器日志"]
|
||||
ReviewLogs --> FixIssue["修复问题"]
|
||||
FixIssue --> VerifyFix["验证修复效果"]
|
||||
```
|
||||
|
||||
**章节来源**
|
||||
- [TsHttpUtil.js:7-23](file://src/https/TsHttpUtil.js#L7-L23)
|
||||
- [TsHttpUtil.js:28-35](file://src/https/TsHttpUtil.js#L28-L35)
|
||||
|
||||
### 加密解密故障排除
|
||||
|
||||
#### 常见加密问题
|
||||
|
||||
**1. 密钥长度错误**
|
||||
- **症状**: 抛出 "key should be a 16 bytes string" 错误
|
||||
- **原因**: 密钥不是 16 字节长度
|
||||
- **解决方案**:
|
||||
- 确保 base64Key 正确且长度为 24 字节(对应 16 字节二进制)
|
||||
- 验证密钥格式和编码
|
||||
|
||||
**2. IV 初始化向量错误**
|
||||
- **症状**: 抛出 "iv error" 错误
|
||||
- **原因**: CBC 模式下的 IV 不是 16 字节
|
||||
- **解决方案**:
|
||||
- 确保 IV 参数存在且长度为 16 字节
|
||||
- 检查 IV 的生成和传递过程
|
||||
|
||||
**3. 加密数据解密失败**
|
||||
- **症状**: 解密后得到乱码或抛出异常
|
||||
- **原因**: 数据被篡改或密钥不匹配
|
||||
- **解决方案**:
|
||||
- 验证数据完整性
|
||||
- 确认使用相同的密钥和模式
|
||||
- 检查 Base64 编码/解码过程
|
||||
|
||||
#### 加密调试流程
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start[开始加密调试] --> CheckKey["检查密钥配置"]
|
||||
CheckKey --> KeyValid{"密钥有效?"}
|
||||
KeyValid --> |否| FixKey["修复密钥配置"]
|
||||
KeyValid --> |是| CheckMode["检查加密模式"]
|
||||
CheckMode --> ModeValid{"模式正确?"}
|
||||
ModeValid --> |否| FixMode["修复模式配置"]
|
||||
ModeValid --> |是| TestEncrypt["测试加密功能"]
|
||||
TestEncrypt --> EncryptSuccess{"加密成功?"}
|
||||
EncryptSuccess --> |否| DebugEncrypt["调试加密过程"]
|
||||
EncryptSuccess --> |是| TestDecrypt["测试解密功能"]
|
||||
TestDecrypt --> DecryptSuccess{"解密成功?"}
|
||||
DecryptSuccess --> |否| DebugDecrypt["调试解密过程"]
|
||||
DecryptSuccess --> |是| Complete[完成调试]
|
||||
DebugEncrypt --> FixEncrypt["修复加密问题"]
|
||||
DebugDecrypt --> FixDecrypt["修复解密问题"]
|
||||
FixKey --> CheckKey
|
||||
FixMode --> CheckMode
|
||||
FixEncrypt --> TestEncrypt
|
||||
FixDecrypt --> TestDecrypt
|
||||
```
|
||||
|
||||
**章节来源**
|
||||
- [TsSM4.js:102-123](file://src/utils/TsSM4.js#L102-L123)
|
||||
- [TsSM4.js:345-347](file://src/utils/TsSM4.js#L345-L347)
|
||||
- [TsSM4.js:410-412](file://src/utils/TsSM4.js#L410-L412)
|
||||
|
||||
### 存储访问异常
|
||||
|
||||
#### 常见存储问题
|
||||
|
||||
**1. localStorage 访问失败**
|
||||
- **症状**: 抛出 SecurityError 或 QuotaExceededError
|
||||
- **原因**: 浏览器安全策略或存储配额限制
|
||||
- **解决方案**:
|
||||
- 检查浏览器隐私设置
|
||||
- 清理过期的存储数据
|
||||
- 实现存储容量监控
|
||||
|
||||
**2. 数据序列化失败**
|
||||
- **症状**: JSON.stringify 抛出异常
|
||||
- **原因**: 循环引用或不可序列化对象
|
||||
- **解决方案**:
|
||||
- 避免存储循环引用的对象
|
||||
- 使用自定义序列化方法
|
||||
- 过滤不可序列化的属性
|
||||
|
||||
**3. 数据获取为空**
|
||||
- **症状**: Storage.get 返回空值或默认值
|
||||
- **原因**: 数据未正确存储或键名不匹配
|
||||
- **解决方案**:
|
||||
- 验证存储键名的一致性
|
||||
- 检查存储前的数据格式
|
||||
- 实现数据完整性检查
|
||||
|
||||
#### 存储调试方法
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
StorageError[存储问题] --> CheckBrowser["检查浏览器兼容性"]
|
||||
CheckBrowser --> VerifyStorage["验证存储可用性"]
|
||||
VerifyStorage --> TestWrite["测试写入功能"]
|
||||
TestWrite --> WriteSuccess{"写入成功?"}
|
||||
WriteSuccess --> |否| FixWrite["修复写入问题"]
|
||||
WriteSuccess --> |是| TestRead["测试读取功能"]
|
||||
TestRead --> ReadSuccess{"读取成功?"}
|
||||
ReadSuccess --> |否| FixRead["修复读取问题"]
|
||||
ReadSuccess --> |是| CheckData["检查数据完整性"]
|
||||
CheckData --> Complete[问题解决]
|
||||
FixWrite --> VerifyStorage
|
||||
FixRead --> TestWrite
|
||||
```
|
||||
|
||||
**章节来源**
|
||||
- [TsStorage.js:31-43](file://src/utils/TsStorage.js#L31-L43)
|
||||
|
||||
### 配置相关问题
|
||||
|
||||
#### 全局配置故障排除
|
||||
|
||||
**1. 配置项缺失**
|
||||
- **症状**: 配置获取失败或返回默认值
|
||||
- **原因**: window.httpConfig 未正确初始化
|
||||
- **解决方案**:
|
||||
- 确保在应用启动时调用 setConfig
|
||||
- 验证配置对象的完整性
|
||||
- 检查配置项的命名一致性
|
||||
|
||||
**2. 动态配置更新失败**
|
||||
- **症状**: 配置更新后仍使用旧值
|
||||
- **原因**: 配置缓存或作用域问题
|
||||
- **解决方案**:
|
||||
- 确保使用最新的配置对象
|
||||
- 验证配置更新的时机
|
||||
- 检查配置的作用域范围
|
||||
|
||||
**章节来源**
|
||||
- [TsGlobalConfig.js:19-29](file://src/utils/TsGlobalConfig.js#L19-L29)
|
||||
|
||||
### 日志记录和监控最佳实践
|
||||
|
||||
#### 日志记录策略
|
||||
|
||||
1. **错误日志**
|
||||
- 记录完整的错误堆栈信息
|
||||
- 包含请求参数和响应数据
|
||||
- 添加时间戳和上下文信息
|
||||
|
||||
2. **性能日志**
|
||||
- 记录请求耗时和响应大小
|
||||
- 监控加密解密性能
|
||||
- 跟踪存储操作的性能
|
||||
|
||||
3. **调试日志**
|
||||
- 在开发环境中启用详细日志
|
||||
- 区分不同级别的日志信息
|
||||
- 提供可配置的日志级别
|
||||
|
||||
#### 监控指标
|
||||
|
||||
1. **网络请求指标**
|
||||
- 请求成功率和失败率
|
||||
- 平均响应时间和最大响应时间
|
||||
- 错误类型分布统计
|
||||
|
||||
2. **加密性能指标**
|
||||
- 加密/解密耗时统计
|
||||
- 数据大小与处理时间的关系
|
||||
- 内存使用情况监控
|
||||
|
||||
3. **存储性能指标**
|
||||
- 存储操作成功率
|
||||
- 数据读取/写入延迟
|
||||
- 存储空间使用率
|
||||
|
||||
### 性能问题诊断和优化
|
||||
|
||||
#### 网络性能诊断
|
||||
|
||||
1. **请求分析**
|
||||
- 使用浏览器开发者工具分析网络请求
|
||||
- 检查请求头和响应头的大小
|
||||
- 识别慢请求和异常请求
|
||||
|
||||
2. **缓存策略**
|
||||
- 实现合理的缓存策略
|
||||
- 避免不必要的重复请求
|
||||
- 优化缓存失效机制
|
||||
|
||||
3. **连接池管理**
|
||||
- 合理管理 HTTP 连接
|
||||
- 避免连接泄漏
|
||||
- 优化并发请求数量
|
||||
|
||||
#### 加密性能优化
|
||||
|
||||
1. **算法选择**
|
||||
- 根据数据大小选择合适的加密算法
|
||||
- 考虑硬件加速支持
|
||||
- 评估加密强度与性能的平衡
|
||||
|
||||
2. **内存管理**
|
||||
- 及时释放加密相关的内存
|
||||
- 避免内存泄漏
|
||||
- 监控内存使用情况
|
||||
|
||||
3. **批处理优化**
|
||||
- 对大量数据进行批处理
|
||||
- 减少加密调用次数
|
||||
- 实现异步处理机制
|
||||
|
||||
#### 存储性能优化
|
||||
|
||||
1. **数据组织**
|
||||
- 合理组织存储的数据结构
|
||||
- 避免过大的单个存储项
|
||||
- 实现数据分片存储
|
||||
|
||||
2. **访问模式优化**
|
||||
- 优化数据的读取和写入模式
|
||||
- 实现缓存机制
|
||||
- 减少存储操作的频率
|
||||
|
||||
3. **容量管理**
|
||||
- 监控存储空间使用情况
|
||||
- 实现自动清理机制
|
||||
- 提供存储容量预警
|
||||
|
||||
## 结论
|
||||
|
||||
npm-tool 工具包提供了完整的前端开发基础设施,涵盖了网络请求、数据加密解密、本地存储和通用工具等多个方面。通过本文档提供的故障排除指南和最佳实践建议,开发者可以更有效地识别和解决使用过程中遇到的各种问题。
|
||||
|
||||
关键要点包括:
|
||||
- 建立系统性的调试流程和方法
|
||||
- 理解各组件之间的依赖关系和交互方式
|
||||
- 实施适当的性能监控和优化策略
|
||||
- 建立完善的错误处理和日志记录机制
|
||||
|
||||
对于复杂问题,建议按照本文档提供的诊断流程逐步排查,从最简单的配置问题开始,逐步深入到复杂的算法和性能问题。同时,结合实际应用场景的特点,制定相应的预防措施和应急方案。
|
||||
446
.qoder/repowiki/zh/content/故障排除/网络请求问题.md
Normal file
446
.qoder/repowiki/zh/content/故障排除/网络请求问题.md
Normal file
@@ -0,0 +1,446 @@
|
||||
# 网络请求问题
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [TsHttpUtil.js](file://src/https/TsHttpUtil.js)
|
||||
- [TsGlobalConfig.js](file://src/utils/TsGlobalConfig.js)
|
||||
- [TsStorage.js](file://src/utils/TsStorage.js)
|
||||
- [TsCommon.js](file://src/utils/TsCommon.js)
|
||||
- [TsCrypto.js](file://src/utils/TsCrypto.js)
|
||||
- [TsSM4.js](file://src/utils/TsSM4.js)
|
||||
- [index.js](file://index.js)
|
||||
- [package.json](file://package.json)
|
||||
- [README.md](file://README.md)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能与可靠性考虑](#性能与可靠性考虑)
|
||||
8. [故障排除指南](#故障排除指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本指南聚焦于网络请求相关的故障排除,结合仓库中网络请求封装与工具模块,系统梳理常见 HTTP 错误(如 401/403、404、500、502、503、504)、跨域问题、请求超时、参数与 URL 前缀配置错误、Cookie 传递问题以及加解密与全局配置的影响因素。文档提供可落地的排查步骤、调试工具使用建议与日志分析流程,帮助快速定位与解决问题。
|
||||
|
||||
## 项目结构
|
||||
该工具包以“网络请求封装 + 工具模块”为核心,对外通过统一入口导出,便于在业务层集中管理请求行为与全局配置。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
A["index.js<br/>统一导出"] --> B["src/https/TsHttpUtil.js<br/>请求封装与错误处理"]
|
||||
A --> C["src/utils/TsGlobalConfig.js<br/>全局配置"]
|
||||
A --> D["src/utils/TsStorage.js<br/>本地存储与Token/Cookie相关"]
|
||||
A --> E["src/utils/TsCommon.js<br/>通用工具"]
|
||||
A --> F["src/utils/TsCrypto.js<br/>加密/解密"]
|
||||
F --> G["src/utils/TsSM4.js<br/>SM4实现"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [index.js:1-16](file://index.js#L1-L16)
|
||||
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
|
||||
- [TsGlobalConfig.js:1-34](file://src/utils/TsGlobalConfig.js#L1-L34)
|
||||
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
|
||||
- [TsCommon.js:1-98](file://src/utils/TsCommon.js#L1-L98)
|
||||
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
|
||||
- [TsSM4.js:1-456](file://src/utils/TsSM4.js#L1-L456)
|
||||
|
||||
章节来源
|
||||
- [index.js:1-16](file://index.js#L1-L16)
|
||||
- [package.json:1-24](file://package.json#L1-L24)
|
||||
|
||||
## 核心组件
|
||||
- 请求封装与错误处理:基于 umi-request 的扩展,统一设置默认参数(携带 Cookie、JSON 请求体),内置错误映射与兜底处理。
|
||||
- 全局配置:提供前缀、额外参数注入、HTTP 错误回调等可插拔配置项。
|
||||
- 存储与 Token:负责用户 Token 的读取与持久化,以及是否启用请求体加密的开关。
|
||||
- 加密模块:基于 SM4 的加解密实现,支持 ECB 模式与 Base64 输出。
|
||||
- 通用工具:空值判断、JSON 解析、URL 参数解析等基础能力。
|
||||
|
||||
章节来源
|
||||
- [TsHttpUtil.js:7-35](file://src/https/TsHttpUtil.js#L7-L35)
|
||||
- [TsHttpUtil.js:40-44](file://src/https/TsHttpUtil.js#L40-L44)
|
||||
- [TsHttpUtil.js:99-134](file://src/https/TsHttpUtil.js#L99-L134)
|
||||
- [TsGlobalConfig.js:5-29](file://src/utils/TsGlobalConfig.js#L5-L29)
|
||||
- [TsStorage.js:9-23](file://src/utils/TsStorage.js#L9-L23)
|
||||
- [TsCrypto.js:5-31](file://src/utils/TsCrypto.js#L5-L31)
|
||||
- [TsSM4.js:96-156](file://src/utils/TsSM4.js#L96-L156)
|
||||
- [TsCommon.js:25-44](file://src/utils/TsCommon.js#L25-L44)
|
||||
|
||||
## 架构总览
|
||||
下图展示从调用方到网络层的关键交互路径,以及错误处理与加解密的插入点。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Caller as "调用方"
|
||||
participant Http as "TsHttpUtil.req"
|
||||
participant Conf as "TsGlobalConfig"
|
||||
participant Store as "TsStorage"
|
||||
participant Crypto as "TsCrypto"
|
||||
participant Umi as "umi-request"
|
||||
participant Srv as "后端服务"
|
||||
Caller->>Http : "发起请求(get/post/form)"
|
||||
Http->>Conf : "读取全局配置(prefix/httpParams/onHttpError)"
|
||||
Http->>Store : "读取用户Token"
|
||||
Http->>Http : "组装参数/附加额外参数/可选加密"
|
||||
Http->>Umi : "执行请求(携带Cookie/JSON)"
|
||||
Umi-->>Http : "响应/错误"
|
||||
Http->>Crypto : "若响应标记加密则解密"
|
||||
Http-->>Caller : "返回标准化结果或抛出错误"
|
||||
Http->>Conf : "非200时触发onHttpError(res)"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [TsHttpUtil.js:99-134](file://src/https/TsHttpUtil.js#L99-L134)
|
||||
- [TsHttpUtil.js:100-106](file://src/https/TsHttpUtil.js#L100-L106)
|
||||
- [TsHttpUtil.js:109-111](file://src/https/TsHttpUtil.js#L109-L111)
|
||||
- [TsHttpUtil.js:117-128](file://src/https/TsHttpUtil.js#L117-L128)
|
||||
- [TsGlobalConfig.js:19-29](file://src/utils/TsGlobalConfig.js#L19-L29)
|
||||
- [TsStorage.js:13-15](file://src/utils/TsStorage.js#L13-L15)
|
||||
- [TsCrypto.js:19-30](file://src/utils/TsCrypto.js#L19-L30)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 请求封装与错误处理(TsHttpUtil)
|
||||
- 默认行为
|
||||
- 默认携带 Cookie(credentials: include),确保跨子域与第三方 Cookie 场景可用。
|
||||
- 默认 JSON 请求体(requestType: json),POST 表单需显式选择 form。
|
||||
- 统一错误处理:将响应状态映射为可读消息,未捕获时兜底为“参数错误或服务器异常”。
|
||||
- 参数处理
|
||||
- 支持分页参数转换(pagination -> pageNum/pageSize)。
|
||||
- 支持 equals 对象转逗号分隔字符串。
|
||||
- 支持全局额外参数注入(GET 合并 params;非表单 POST 合并 data)。
|
||||
- 可选请求体加密:当开启 encrypt_body 时,将 data 包装为 encryptData 并加密。
|
||||
- URL 前缀
|
||||
- prefix 支持字符串或函数,函数形式可按 URL 动态决定前缀,避免硬编码。
|
||||
- 响应处理
|
||||
- 当 rawResponse 为真时直接返回原始响应;否则仅返回 data 与 recordsTotal。
|
||||
- 若响应标记加密,自动解密并解析 JSON。
|
||||
- 非 200 时触发 onHttpError 回调,同时 reject 标准化错误对象。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["进入 req"]) --> Prefix["读取全局配置prefix"]
|
||||
Prefix --> HasPrefix{"prefix存在?"}
|
||||
HasPrefix --> |是| Join["拼接url = prefix + url"]
|
||||
HasPrefix --> |否| Skip["保持原url"]
|
||||
Join --> Params["dealParamsBody处理参数/附加额外参数/可选加密"]
|
||||
Skip --> Params
|
||||
Params --> Headers["合并headers并注入用户Token"]
|
||||
Headers --> Send["umi-request发送请求"]
|
||||
Send --> Resp{"rawResponse?"}
|
||||
Resp --> |是| ReturnRaw["返回原始响应"]
|
||||
Resp --> |否| Code{"响应码=200?"}
|
||||
Code --> |是| Decrypt{"响应标记加密?"}
|
||||
Decrypt --> |是| Dec["解密+JSON解析"] --> ReturnData["返回{data,recordsTotal}"]
|
||||
Decrypt --> |否| ReturnData
|
||||
Code --> |否| Hook["触发onHttpError(res)"] --> Reject["reject标准化错误"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [TsHttpUtil.js:99-134](file://src/https/TsHttpUtil.js#L99-L134)
|
||||
- [TsHttpUtil.js:50-91](file://src/https/TsHttpUtil.js#L50-L91)
|
||||
- [TsHttpUtil.js:117-128](file://src/https/TsHttpUtil.js#L117-L128)
|
||||
|
||||
章节来源
|
||||
- [TsHttpUtil.js:7-35](file://src/https/TsHttpUtil.js#L7-L35)
|
||||
- [TsHttpUtil.js:40-44](file://src/https/TsHttpUtil.js#L40-L44)
|
||||
- [TsHttpUtil.js:50-91](file://src/https/TsHttpUtil.js#L50-L91)
|
||||
- [TsHttpUtil.js:99-134](file://src/https/TsHttpUtil.js#L99-L134)
|
||||
|
||||
### 全局配置(TsGlobalConfig)
|
||||
- 关键配置项
|
||||
- base64Key:用于初始化加密模块的密钥缓冲区。
|
||||
- prefix:统一请求前缀,支持函数按 URL 动态生成。
|
||||
- onHttpError:非 200 时的回调钩子,便于统一处理错误。
|
||||
- httpParams:返回额外参数对象,GET 合并到 params,POST 合并到 data。
|
||||
- 读写方式
|
||||
- 通过 window.httpConfig 注入全局配置,setConfig 支持增量合并。
|
||||
|
||||
章节来源
|
||||
- [TsGlobalConfig.js:5-29](file://src/utils/TsGlobalConfig.js#L5-L29)
|
||||
- [TsGlobalConfig.js:19-29](file://src/utils/TsGlobalConfig.js#L19-L29)
|
||||
|
||||
### 存储与 Token(TsStorage)
|
||||
- 用户 Token
|
||||
- 读取:getUserToken 从本地存储获取,为空时返回空字符串。
|
||||
- 写入:saveUserToken 将 Token 持久化。
|
||||
- 请求体加密开关
|
||||
- getEncryptBody/getSaveEncryptBody 控制是否对请求体进行加密包装。
|
||||
- Cookie 传递
|
||||
- 默认 credentials: include,配合后端 SameSite/Cross-Origin 策略使用。
|
||||
|
||||
章节来源
|
||||
- [TsStorage.js:9-23](file://src/utils/TsStorage.js#L9-L23)
|
||||
|
||||
### 加密模块(TsCrypto 与 TsSM4)
|
||||
- 初始化
|
||||
- 使用 base64Key 生成 16 字节密钥缓冲区,构造 SM4 实例。
|
||||
- 加密/解密
|
||||
- encrypt:对明文进行 SM4 加密(ECB 模式,Base64 输出)。
|
||||
- decrypt:对密文进行 SM4 解密。
|
||||
- 注意事项
|
||||
- ECB 模式无 IV,适合小块数据;CBC 需要 IV,当前实现未使用 IV。
|
||||
- cipherType 默认 Base64,与前端期望一致。
|
||||
|
||||
章节来源
|
||||
- [TsCrypto.js:5-31](file://src/utils/TsCrypto.js#L5-L31)
|
||||
- [TsSM4.js:96-156](file://src/utils/TsSM4.js#L96-L156)
|
||||
- [TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387)
|
||||
- [TsSM4.js:395-452](file://src/utils/TsSM4.js#L395-L452)
|
||||
|
||||
## 依赖关系分析
|
||||
- TsHttpUtil 依赖
|
||||
- TsGlobalConfig:读取 prefix、httpParams、onHttpError。
|
||||
- TsStorage:读取用户 Token、加密开关。
|
||||
- TsCrypto:在开启加密时对请求体进行加密。
|
||||
- TsCommon:参数处理与空值判断。
|
||||
- TsCrypto 依赖
|
||||
- TsGlobalConfig:读取 base64Key。
|
||||
- TsSM4:SM4 算法实现。
|
||||
- 外部依赖
|
||||
- umi-request:HTTP 请求库。
|
||||
- base64-js:Base64 编解码。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Http["TsHttpUtil"] --> Conf["TsGlobalConfig"]
|
||||
Http --> Store["TsStorage"]
|
||||
Http --> Crypto["TsCrypto"]
|
||||
Http --> Common["TsCommon"]
|
||||
Crypto --> SM4["TsSM4"]
|
||||
Http --> Umi["umi-request"]
|
||||
Crypto --> Base64["base64-js"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [TsHttpUtil.js:1-6](file://src/https/TsHttpUtil.js#L1-L6)
|
||||
- [TsCrypto.js:1-4](file://src/utils/TsCrypto.js#L1-L4)
|
||||
- [package.json:19-22](file://package.json#L19-L22)
|
||||
|
||||
章节来源
|
||||
- [TsHttpUtil.js:1-6](file://src/https/TsHttpUtil.js#L1-L6)
|
||||
- [TsCrypto.js:1-4](file://src/utils/TsCrypto.js#L1-L4)
|
||||
- [package.json:19-22](file://package.json#L19-L22)
|
||||
|
||||
## 性能与可靠性考虑
|
||||
- 请求并发与重试
|
||||
- 当前未内置重试机制,建议在上层业务根据错误类型(如 502/503/504)进行指数退避重试。
|
||||
- 超时控制
|
||||
- 可通过 umi-request 的 timeout 配置项在扩展层增加超时控制,避免长时间阻塞。
|
||||
- 日志与监控
|
||||
- 在 onHttpError 中接入埋点或上报,记录状态码、URL、耗时、Token 状态等,便于后续分析。
|
||||
- 加密开销
|
||||
- 对大体量请求体加密会带来 CPU 开销,建议仅对敏感数据启用加密。
|
||||
|
||||
[本节为通用建议,不直接分析具体文件]
|
||||
|
||||
## 故障排除指南
|
||||
|
||||
### 一、常见 HTTP 错误与处理策略
|
||||
- 200 成功
|
||||
- 正常流程,无需处理。
|
||||
- 201/202/204
|
||||
- 业务状态正常,关注业务语义与后续处理。
|
||||
- 400 客户端参数错误
|
||||
- 排查请求体格式、必填字段、分页参数转换逻辑(pageNum/pageSize)。
|
||||
- 401 未认证/令牌无效
|
||||
- 检查 Token 是否存在、是否过期、是否正确写入存储。
|
||||
- 确认请求头是否注入了 Token。
|
||||
- 403 权限不足
|
||||
- 检查用户角色与接口权限,确认 Token 有效但无访问权限。
|
||||
- 404 资源不存在
|
||||
- 检查 URL 是否正确、前缀是否匹配、路径参数是否缺失。
|
||||
- 406/410/422
|
||||
- 406:请求格式不可得;410:资源永久删除;422:创建对象时验证错误。
|
||||
- 500 服务器内部错误
|
||||
- 记录请求上下文,联系后端排查。
|
||||
- 502/503/504 网关/服务不可用/网关超时
|
||||
- 建议重试与降级策略,必要时提示用户稍后再试。
|
||||
|
||||
章节来源
|
||||
- [TsHttpUtil.js:7-23](file://src/https/TsHttpUtil.js#L7-L23)
|
||||
- [TsHttpUtil.js:28-35](file://src/https/TsHttpUtil.js#L28-L35)
|
||||
|
||||
### 二、跨域请求失败排查
|
||||
- 关键点
|
||||
- 浏览器同源策略限制,需后端设置正确的 Access-Control-Allow-*。
|
||||
- 若携带 Cookie,需确保:
|
||||
- credentials: include 生效(默认已开启)。
|
||||
- 后端允许 Credentials(Access-Control-Allow-Credentials: true)。
|
||||
- 前端指定具体 Origin(而非通配符),后端允许该 Origin。
|
||||
- 建议
|
||||
- 使用浏览器开发者工具 Network 面板查看预检请求与响应头。
|
||||
- 确认域名、协议、端口一致或后端明确放行。
|
||||
|
||||
章节来源
|
||||
- [TsHttpUtil.js:42](file://src/https/TsHttpUtil.js#L42)
|
||||
|
||||
### 三、请求超时
|
||||
- 现状
|
||||
- 当前未设置超时时间,可能出现长时间等待。
|
||||
- 建议
|
||||
- 在扩展层增加 timeout 配置,或在上层业务做超时控制。
|
||||
- 对长耗时接口采用分页/分批策略。
|
||||
|
||||
[本节为通用建议,不直接分析具体文件]
|
||||
|
||||
### 四、401/403 权限错误
|
||||
- 常见原因
|
||||
- Token 不存在或为空。
|
||||
- Token 过期或被撤销。
|
||||
- 请求头未注入 Token。
|
||||
- 排查步骤
|
||||
- 检查存储中是否存在 Token。
|
||||
- 确认请求头是否包含 Token。
|
||||
- 若后端要求特定头名,需在上层统一注入。
|
||||
- 处理策略
|
||||
- 401:跳转登录或刷新 Token。
|
||||
- 403:提示权限不足或引导用户联系管理员。
|
||||
|
||||
章节来源
|
||||
- [TsStorage.js:13-15](file://src/utils/TsStorage.js#L13-L15)
|
||||
- [TsHttpUtil.js:109-111](file://src/https/TsHttpUtil.js#L109-L111)
|
||||
|
||||
### 五、500 服务器错误
|
||||
- 建议
|
||||
- 记录完整请求上下文(URL、params/data、headers、Token)。
|
||||
- 在 onHttpError 中接入日志上报,便于后端定位。
|
||||
- 必要时进行降级或重试。
|
||||
|
||||
章节来源
|
||||
- [TsHttpUtil.js:125](file://src/https/TsHttpUtil.js#L125)
|
||||
|
||||
### 六、请求参数配置问题
|
||||
- 分页参数
|
||||
- pagination 转换为 pageNum/pageSize,确认传入对象结构正确。
|
||||
- equals 对象
|
||||
- equals 对象中空值会被过滤,确保非空字段参与拼接。
|
||||
- 全局额外参数
|
||||
- httpParams 返回的对象会合并到 GET params 或 POST data,注意字段冲突与覆盖顺序。
|
||||
|
||||
章节来源
|
||||
- [TsHttpUtil.js:50-91](file://src/https/TsHttpUtil.js#L50-L91)
|
||||
- [TsGlobalConfig.js:10-12](file://src/utils/TsGlobalConfig.js#L10-L12)
|
||||
|
||||
### 七、URL 前缀配置错误
|
||||
- 现状
|
||||
- prefix 支持字符串或函数;函数形式可按 URL 动态生成。
|
||||
- 排查
|
||||
- 确认 prefix 是否为空或返回空字符串。
|
||||
- 函数形式需保证返回值为合法前缀(含协议与结尾斜杠)。
|
||||
- 建议
|
||||
- 在开发环境与生产环境分别设置不同前缀,避免硬编码。
|
||||
|
||||
章节来源
|
||||
- [TsHttpUtil.js:100-106](file://src/https/TsHttpUtil.js#L100-L106)
|
||||
- [TsGlobalConfig.js:7](file://src/utils/TsGlobalConfig.js#L7)
|
||||
|
||||
### 八、Cookie 传递问题
|
||||
- 现状
|
||||
- 默认携带 Cookie(credentials: include),适用于同源与跨子域场景。
|
||||
- 排查
|
||||
- 确认后端是否正确设置 Domain/SameSite/Cross-Origin。
|
||||
- 若跨域,需后端允许 Credentials 且指定具体 Origin。
|
||||
- 建议
|
||||
- 在上层统一设置 Cookie 与 Token,避免遗漏。
|
||||
|
||||
章节来源
|
||||
- [TsHttpUtil.js:42](file://src/https/TsHttpUtil.js#L42)
|
||||
|
||||
### 九、加解密相关问题
|
||||
- 现状
|
||||
- 当开启 encrypt_body 时,请求体被包装为 encryptData 并加密;响应若标记加密则自动解密。
|
||||
- 排查
|
||||
- 确认 base64Key 与后端一致。
|
||||
- 确认加密模式(ECB)与后端一致。
|
||||
- 确认 cipherType 为 Base64。
|
||||
- 建议
|
||||
- 仅对敏感字段启用加密,避免大体积数据加密带来的性能损耗。
|
||||
|
||||
章节来源
|
||||
- [TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23)
|
||||
- [TsHttpUtil.js:82-86](file://src/https/TsHttpUtil.js#L82-L86)
|
||||
- [TsHttpUtil.js:119-122](file://src/https/TsHttpUtil.js#L119-L122)
|
||||
- [TsCrypto.js:8-13](file://src/utils/TsCrypto.js#L8-L13)
|
||||
- [TsSM4.js:128-141](file://src/utils/TsSM4.js#L128-L141)
|
||||
|
||||
### 十、调试工具与监控技巧
|
||||
- 浏览器开发者工具
|
||||
- Network:查看请求头、响应头、CORS、Cookie、状态码与耗时。
|
||||
- Console:输出 onHttpError 回调中的错误信息。
|
||||
- 日志与上报
|
||||
- 在 onHttpError 中记录:URL、状态码、请求体摘要、Token 状态、时间戳。
|
||||
- 对 5xx 错误进行聚合统计,辅助定位热点接口。
|
||||
- 本地与线上差异
|
||||
- 使用不同 prefix 区分开发/测试/生产环境。
|
||||
- 在开发环境开启更详细的日志与断言。
|
||||
|
||||
章节来源
|
||||
- [TsHttpUtil.js:125](file://src/https/TsHttpUtil.js#L125)
|
||||
- [TsGlobalConfig.js:7](file://src/utils/TsGlobalConfig.js#L7)
|
||||
|
||||
### 十一、错误日志分析与问题定位流程
|
||||
- 步骤
|
||||
- 收集:URL、状态码、请求头、请求体、响应体、时间戳、Token 状态。
|
||||
- 分类:4xx(参数/权限/资源)、5xx(服务/网关)、CORS/超时。
|
||||
- 定位:依据状态码与日志,缩小范围至前端配置、Cookie/Token、加解密、后端接口。
|
||||
- 复现:构造最小复现场景,逐步剔除变量(关闭加密、更换 prefix、清除 Cookie)。
|
||||
- 验证:修复后回归测试,观察 onHttpError 是否仍触发。
|
||||
- 建议
|
||||
- 对高频错误建立告警阈值,结合用户反馈与日志进行联动。
|
||||
|
||||
[本节为通用建议,不直接分析具体文件]
|
||||
|
||||
## 结论
|
||||
本工具包通过统一的请求封装、全局配置与加解密模块,提供了较为完善的网络请求基础设施。结合本文提供的故障排除清单与定位流程,可在大多数情况下快速识别并解决常见的网络请求问题。建议在生产环境中补充超时控制、重试与监控上报机制,持续优化用户体验与稳定性。
|
||||
|
||||
[本节为总结性内容,不直接分析具体文件]
|
||||
|
||||
## 附录
|
||||
|
||||
### A. 常见错误代码速查
|
||||
- 200:成功
|
||||
- 201:新建/修改成功
|
||||
- 202:请求已进入后台排队
|
||||
- 204:删除成功
|
||||
- 400:请求参数错误
|
||||
- 401:未认证/令牌无效
|
||||
- 403:权限不足
|
||||
- 404:资源不存在
|
||||
- 406:请求格式不可得
|
||||
- 410:资源永久删除
|
||||
- 422:创建对象时验证错误
|
||||
- 500:服务器内部错误
|
||||
- 502:网关错误
|
||||
- 503:服务不可用/过载
|
||||
- 504:网关超时
|
||||
|
||||
章节来源
|
||||
- [TsHttpUtil.js:7-23](file://src/https/TsHttpUtil.js#L7-L23)
|
||||
|
||||
### B. 关键配置与默认值
|
||||
- 默认配置
|
||||
- base64Key:默认密钥(用于加密模块初始化)。
|
||||
- prefix:默认空字符串。
|
||||
- onHttpError:默认空函数。
|
||||
- httpParams:默认空函数。
|
||||
- 请求默认
|
||||
- credentials: include(携带 Cookie)。
|
||||
- requestType: json(POST JSON)。
|
||||
- 默认错误处理:将状态映射为可读消息。
|
||||
|
||||
章节来源
|
||||
- [TsGlobalConfig.js:5-13](file://src/utils/TsGlobalConfig.js#L5-L13)
|
||||
- [TsHttpUtil.js:40-44](file://src/https/TsHttpUtil.js#L40-L44)
|
||||
- [TsHttpUtil.js:28-35](file://src/https/TsHttpUtil.js#L28-L35)
|
||||
|
||||
### C. 使用示例参考
|
||||
- README 提供了基本使用方式与全局配置示例,可据此进行最小复现与验证。
|
||||
|
||||
章节来源
|
||||
- [README.md:12-26](file://README.md#L12-L26)
|
||||
803
.qoder/repowiki/zh/content/故障排除/调试工具和方法.md
Normal file
803
.qoder/repowiki/zh/content/故障排除/调试工具和方法.md
Normal file
@@ -0,0 +1,803 @@
|
||||
# 调试工具和方法
|
||||
|
||||
<cite>
|
||||
**本文档中引用的文件**
|
||||
- [README.md](file://README.md)
|
||||
- [package.json](file://package.json)
|
||||
- [index.js](file://index.js)
|
||||
- [TsCommon.js](file://src/utils/TsCommon.js)
|
||||
- [TsGlobalConfig.js](file://src/utils/TsGlobalConfig.js)
|
||||
- [TsStorage.js](file://src/utils/TsStorage.js)
|
||||
- [TsCrypto.js](file://src/utils/TsCrypto.js)
|
||||
- [TsSM4.js](file://src/utils/TsSM4.js)
|
||||
- [TsHttpUtil.js](file://src/https/TsHttpUtil.js)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构概览](#架构概览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [调试工具集成指南](#调试工具集成指南)
|
||||
7. [调试技术与方法](#调试技术与方法)
|
||||
8. [性能监控与优化](#性能监控与优化)
|
||||
9. [故障排查指南](#故障排查指南)
|
||||
10. [最佳实践总结](#最佳实践总结)
|
||||
|
||||
## 简介
|
||||
|
||||
本指南专注于如何有效使用各种调试工具和技术来诊断和解决基于 Node.js 的 npm 工具包问题。该工具包提供了通用方法、网络请求、存储管理、加密解密等功能模块,涵盖了现代 Web 应用开发中的常见调试场景。
|
||||
|
||||
## 项目结构
|
||||
|
||||
该项目采用模块化设计,主要包含以下核心模块:
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "主入口"
|
||||
Index[index.js]
|
||||
end
|
||||
subgraph "工具模块"
|
||||
Common[TsCommon.js<br/>通用工具函数]
|
||||
Crypto[TsCrypto.js<br/>加密解密]
|
||||
Storage[TsStorage.js<br/>数据存储]
|
||||
Config[TsGlobalConfig.js<br/>全局配置]
|
||||
SM4[TsSM4.js<br/>SM4算法实现]
|
||||
end
|
||||
subgraph "HTTP模块"
|
||||
HttpUtil[TsHttpUtil.js<br/>网络请求封装]
|
||||
end
|
||||
subgraph "依赖"
|
||||
UmiRequest[umi-request<br/>HTTP客户端]
|
||||
Base64[base64-js<br/>Base64编码]
|
||||
end
|
||||
Index --> Common
|
||||
Index --> Crypto
|
||||
Index --> Storage
|
||||
Index --> Config
|
||||
Index --> SM4
|
||||
Index --> HttpUtil
|
||||
HttpUtil --> Storage
|
||||
HttpUtil --> Crypto
|
||||
HttpUtil --> Config
|
||||
HttpUtil --> Common
|
||||
Crypto --> SM4
|
||||
Crypto --> Config
|
||||
Crypto --> Base64
|
||||
HttpUtil --> UmiRequest
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [index.js:1-16](file://index.js#L1-L16)
|
||||
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
|
||||
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
|
||||
|
||||
**章节来源**
|
||||
- [index.js:1-16](file://index.js#L1-L16)
|
||||
- [package.json:1-24](file://package.json#L1-L24)
|
||||
|
||||
## 核心组件
|
||||
|
||||
### 通用工具模块 (TsCommon.js)
|
||||
|
||||
提供基础的 JavaScript 工具函数,包括:
|
||||
- URL 参数解析
|
||||
- 数据类型检查
|
||||
- JSON 解析安全处理
|
||||
- 字符串操作
|
||||
- 环境检测
|
||||
|
||||
### 网络请求模块 (TsHttpUtil.js)
|
||||
|
||||
基于 umi-request 封装的 HTTP 客户端,支持:
|
||||
- 自动错误处理
|
||||
- 请求参数预处理
|
||||
- 数据加密传输
|
||||
- 响应数据解密
|
||||
- Token 自动注入
|
||||
|
||||
### 存储模块 (TsStorage.js)
|
||||
|
||||
本地存储管理,支持:
|
||||
- 对象序列化存储
|
||||
- 用户 Token 管理
|
||||
- 加密开关控制
|
||||
- 类型安全的数据获取
|
||||
|
||||
### 加密模块 (TsCrypto.js)
|
||||
|
||||
基于 SM4 算法的加密解密工具,包含:
|
||||
- SM4 算法实现
|
||||
- Base64 编码支持
|
||||
- 动态密钥处理
|
||||
- 加密模式配置
|
||||
|
||||
**章节来源**
|
||||
- [TsCommon.js:1-98](file://src/utils/TsCommon.js#L1-L98)
|
||||
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
|
||||
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
|
||||
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
|
||||
|
||||
## 架构概览
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as 客户端应用
|
||||
participant HttpUtil as HTTP工具
|
||||
participant Crypto as 加密模块
|
||||
participant Storage as 存储模块
|
||||
participant Server as 服务器
|
||||
Client->>HttpUtil : 发起请求
|
||||
HttpUtil->>Storage : 获取用户Token
|
||||
Storage-->>HttpUtil : 返回Token
|
||||
HttpUtil->>HttpUtil : 处理请求参数
|
||||
HttpUtil->>Crypto : 加密请求数据(可选)
|
||||
Crypto-->>HttpUtil : 返回加密结果
|
||||
HttpUtil->>Server : 发送HTTP请求
|
||||
Server-->>HttpUtil : 返回响应
|
||||
HttpUtil->>Crypto : 解密响应数据(可选)
|
||||
Crypto-->>HttpUtil : 返回解密结果
|
||||
HttpUtil-->>Client : 返回处理后的数据
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsHttpUtil.js:99-134](file://src/https/TsHttpUtil.js#L99-L134)
|
||||
- [TsCrypto.js:19-30](file://src/utils/TsCrypto.js#L19-L30)
|
||||
- [TsStorage.js:9-15](file://src/utils/TsStorage.js#L9-L15)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### HTTP 请求流程分析
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始请求]) --> CheckPrefix["检查URL前缀配置"]
|
||||
CheckPrefix --> AddPrefix["添加URL前缀"]
|
||||
AddPrefix --> ParamsPrep["参数预处理"]
|
||||
ParamsPrep --> CheckEncryption{"检查加密开关"}
|
||||
CheckEncryption --> |开启| EncryptData["加密请求数据"]
|
||||
CheckEncryption --> |关闭| SkipEncrypt["跳过加密"]
|
||||
EncryptData --> AddToken["添加用户Token"]
|
||||
SkipEncrypt --> AddToken
|
||||
AddToken --> SendRequest["发送HTTP请求"]
|
||||
SendRequest --> CheckResponse{"检查响应状态"}
|
||||
CheckResponse --> |成功| DecryptData["解密响应数据(可选)"]
|
||||
CheckResponse --> |失败| ErrorHandler["错误处理"]
|
||||
DecryptData --> ParseJSON["解析JSON数据"]
|
||||
ParseJSON --> ReturnSuccess["返回成功响应"]
|
||||
ErrorHandler --> ReturnError["返回错误响应"]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsHttpUtil.js:99-134](file://src/https/TsHttpUtil.js#L99-L134)
|
||||
- [TsHttpUtil.js:50-91](file://src/https/TsHttpUtil.js#L50-L91)
|
||||
|
||||
### 加密解密流程分析
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class TsCrypto {
|
||||
-SM4 sm4
|
||||
+constructor()
|
||||
+encrypt(content) String
|
||||
+decrypt(base64) String
|
||||
}
|
||||
class TsSM4 {
|
||||
-Uint8Array key
|
||||
-Uint8Array iv
|
||||
-String mode
|
||||
-String cipherType
|
||||
-Uint32Array encryptRoundKeys
|
||||
-Uint32Array decryptRoundKeys
|
||||
+constructor(config)
|
||||
+encrypt(plaintext) String
|
||||
+decrypt(ciphertext) String
|
||||
-padding(buffer) Uint8Array
|
||||
-dePadding(buffer) Uint8Array
|
||||
}
|
||||
class TsGlobalConfig {
|
||||
+defaultConfig
|
||||
+getConfig() Object
|
||||
+setConfig(obj) void
|
||||
}
|
||||
TsCrypto --> TsSM4 : 使用
|
||||
TsCrypto --> TsGlobalConfig : 读取配置
|
||||
TsSM4 --> TsGlobalConfig : 读取密钥
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [TsCrypto.js:5-34](file://src/utils/TsCrypto.js#L5-L34)
|
||||
- [TsSM4.js:96-453](file://src/utils/TsSM4.js#L96-L453)
|
||||
- [TsGlobalConfig.js:19-33](file://src/utils/TsGlobalConfig.js#L19-L33)
|
||||
|
||||
**章节来源**
|
||||
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
|
||||
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
|
||||
- [TsSM4.js:1-456](file://src/utils/TsSM4.js#L1-L456)
|
||||
|
||||
## 调试工具集成指南
|
||||
|
||||
### 浏览器开发者工具调试
|
||||
|
||||
#### 1. 断点设置技巧
|
||||
|
||||
**网络请求断点**:
|
||||
- 在 `TsHttpUtil.js` 的 `req` 函数中设置断点
|
||||
- 检查 `dealParamsBody` 函数中的参数处理逻辑
|
||||
- 监控 `errorHandler` 函数的错误处理流程
|
||||
|
||||
**加密解密断点**:
|
||||
- 在 `TsCrypto.js` 的 `encrypt` 和 `decrypt` 方法中设置断点
|
||||
- 监控 `TsSM4.js` 中的加密算法执行过程
|
||||
- 检查 Base64 编码解码的中间结果
|
||||
|
||||
#### 2. 变量检查方法
|
||||
|
||||
**关键变量监控**:
|
||||
- `window.httpConfig` - 全局配置对象
|
||||
- `localStorage` - 本地存储数据
|
||||
- `process.env.NODE_ENV` - 环境变量
|
||||
- 请求头中的 `token` 字段
|
||||
|
||||
#### 3. 控制台调试命令
|
||||
|
||||
```javascript
|
||||
// 检查全局配置
|
||||
console.log('HTTP配置:', window.httpConfig);
|
||||
|
||||
// 检查存储状态
|
||||
console.log('用户Token:', Storage.getUserToken());
|
||||
console.log('加密开关:', Storage.getEncryptBody());
|
||||
|
||||
// 检查请求参数
|
||||
console.log('请求参数:', dealParamsBody(options));
|
||||
```
|
||||
|
||||
### Node.js 调试器使用
|
||||
|
||||
#### 1. 启动调试会话
|
||||
|
||||
```bash
|
||||
# 使用 inspect 模式启动
|
||||
node --inspect-brk=9229 index.js
|
||||
|
||||
# 或者使用 nodemon 进行热重载调试
|
||||
nodemon --inspect-brk=9229 index.js
|
||||
```
|
||||
|
||||
#### 2. VS Code 调试配置
|
||||
|
||||
创建 `.vscode/launch.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "调试 npm 工具包",
|
||||
"program": "${workspaceFolder}/index.js",
|
||||
"args": [],
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. 条件断点设置
|
||||
|
||||
在 Node.js 中可以设置更精确的断点条件:
|
||||
|
||||
```javascript
|
||||
// 在加密函数中设置条件断点
|
||||
if (typeof content === 'object') {
|
||||
debugger; // 仅当内容为对象时触发
|
||||
}
|
||||
|
||||
// 在特定 URL 时断点
|
||||
if (url.includes('api')) {
|
||||
debugger; // 仅在 API 请求时触发
|
||||
}
|
||||
```
|
||||
|
||||
**章节来源**
|
||||
- [TsHttpUtil.js:28-35](file://src/https/TsHttpUtil.js#L28-L35)
|
||||
- [TsCrypto.js:19-30](file://src/utils/TsCrypto.js#L19-L30)
|
||||
- [TsStorage.js:31-43](file://src/utils/TsStorage.js#L31-L43)
|
||||
|
||||
## 调试技术与方法
|
||||
|
||||
### 日志记录策略
|
||||
|
||||
#### 1. 结构化日志记录
|
||||
|
||||
```javascript
|
||||
// 在关键函数中添加日志
|
||||
function debugLog(operation, data, result) {
|
||||
console.log(`[${new Date().toISOString()}] ${operation}`, {
|
||||
data: JSON.stringify(data),
|
||||
result: JSON.stringify(result),
|
||||
stack: new Error().stack
|
||||
});
|
||||
}
|
||||
|
||||
// 使用示例
|
||||
debugLog('HTTP请求', {url, options}, response);
|
||||
```
|
||||
|
||||
#### 2. 环境特定的日志级别
|
||||
|
||||
```javascript
|
||||
// 开发环境启用详细日志
|
||||
if (Common.isDevelopment()) {
|
||||
console.debug('详细调试信息');
|
||||
console.trace('调用栈跟踪');
|
||||
}
|
||||
|
||||
// 生产环境限制日志输出
|
||||
console.warn('警告信息');
|
||||
console.error('错误信息');
|
||||
```
|
||||
|
||||
#### 3. 性能日志记录
|
||||
|
||||
```javascript
|
||||
// 记录函数执行时间
|
||||
function performanceLog(funcName, callback) {
|
||||
const start = performance.now();
|
||||
try {
|
||||
const result = callback();
|
||||
const end = performance.now();
|
||||
console.log(`${funcName} 执行时间: ${end - start}ms`);
|
||||
return result;
|
||||
} catch (error) {
|
||||
const end = performance.now();
|
||||
console.error(`${funcName} 执行失败: ${end - start}ms`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 错误追踪方法
|
||||
|
||||
#### 1. 异步错误处理
|
||||
|
||||
```javascript
|
||||
// 在 Promise 中添加错误处理
|
||||
async function safeRequest(url, options) {
|
||||
try {
|
||||
const response = await req(url, options);
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('请求失败:', {
|
||||
url,
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
timestamp: new Date()
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 错误边界捕获
|
||||
|
||||
```javascript
|
||||
// 全局错误捕获
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
console.error('未处理的 Promise 拒绝:', {
|
||||
reason: reason.message,
|
||||
stack: reason.stack,
|
||||
promise: promise
|
||||
});
|
||||
});
|
||||
|
||||
process.on('uncaughtException', (error) => {
|
||||
console.error('未捕获的异常:', {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
timestamp: new Date()
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### 3. 调试信息收集
|
||||
|
||||
```javascript
|
||||
// 收集调试信息的工具函数
|
||||
function collectDebugInfo() {
|
||||
return {
|
||||
timestamp: new Date(),
|
||||
environment: process.env.NODE_ENV,
|
||||
userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'Node.js',
|
||||
memory: process.memoryUsage(),
|
||||
config: {
|
||||
httpConfig: window.httpConfig,
|
||||
encryptBody: Storage.getEncryptBody()
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 性能监控技巧
|
||||
|
||||
#### 1. 内存使用监控
|
||||
|
||||
```javascript
|
||||
// 监控内存使用情况
|
||||
function monitorMemory() {
|
||||
const usage = process.memoryUsage();
|
||||
console.log('内存使用:', {
|
||||
rss: `${Math.round(usage.rss / 1024 / 1024)} MB`,
|
||||
heapTotal: `${Math.round(usage.heapTotal / 1024 / 1024)} MB`,
|
||||
heapUsed: `${Math.round(usage.heapUsed / 1024 / 1024)} MB`
|
||||
});
|
||||
}
|
||||
|
||||
// 定期监控
|
||||
setInterval(monitorMemory, 5000);
|
||||
```
|
||||
|
||||
#### 2. 网络性能监控
|
||||
|
||||
```javascript
|
||||
// 监控 HTTP 请求性能
|
||||
function monitorHttpRequest(url, startTime, endTime, status) {
|
||||
const duration = endTime - startTime;
|
||||
console.log('HTTP 请求性能:', {
|
||||
url,
|
||||
duration: `${duration}ms`,
|
||||
status,
|
||||
timestamp: new Date()
|
||||
});
|
||||
|
||||
// 性能阈值告警
|
||||
if (duration > 3000) {
|
||||
console.warn(`慢请求警告: ${url} (${duration}ms)`);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. 加密性能监控
|
||||
|
||||
```javascript
|
||||
// 监控加密解密性能
|
||||
function monitorCryptoOperation(operation, dataLength, startTime, endTime) {
|
||||
const duration = endTime - startTime;
|
||||
console.log(`${operation} 性能:`, {
|
||||
dataLength: `${dataLength} 字节`,
|
||||
duration: `${duration}ms`,
|
||||
throughput: `${(dataLength / duration).toFixed(2)} 字节/ms`
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
**章节来源**
|
||||
- [TsCommon.js:63-65](file://src/utils/TsCommon.js#L63-L65)
|
||||
- [TsHttpUtil.js:7-23](file://src/https/TsHttpUtil.js#L7-L23)
|
||||
- [TsCrypto.js:19-30](file://src/utils/TsCrypto.js#L19-L30)
|
||||
|
||||
## 故障排查指南
|
||||
|
||||
### 常见问题诊断
|
||||
|
||||
#### 1. 网络请求问题
|
||||
|
||||
**问题症状**:
|
||||
- 请求超时
|
||||
- 401 未授权
|
||||
- CORS 跨域错误
|
||||
|
||||
**诊断步骤**:
|
||||
1. 检查 Token 是否正确设置
|
||||
2. 验证 URL 前缀配置
|
||||
3. 确认请求头设置
|
||||
4. 检查服务器响应格式
|
||||
|
||||
```javascript
|
||||
// 调试网络请求
|
||||
function debugNetworkRequest(url, options) {
|
||||
console.log('请求详情:', {
|
||||
url: url,
|
||||
options: JSON.stringify(options),
|
||||
token: Storage.getUserToken(),
|
||||
config: GlobalConfig.getConfig()
|
||||
});
|
||||
|
||||
return req(url, options)
|
||||
.catch(error => {
|
||||
console.error('请求失败:', {
|
||||
url: url,
|
||||
error: error.message,
|
||||
response: error.response,
|
||||
stack: error.stack
|
||||
});
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 加密解密问题
|
||||
|
||||
**问题症状**:
|
||||
- 解密失败
|
||||
- 数据损坏
|
||||
- 性能问题
|
||||
|
||||
**诊断步骤**:
|
||||
1. 验证密钥配置
|
||||
2. 检查数据格式
|
||||
3. 确认加密模式
|
||||
4. 监控性能指标
|
||||
|
||||
```javascript
|
||||
// 调试加密解密
|
||||
function debugCryptoOperation(operation, data) {
|
||||
console.log(`${operation} 输入:`, {
|
||||
data: data,
|
||||
dataType: typeof data,
|
||||
dataLength: data ? data.length : 0
|
||||
});
|
||||
|
||||
try {
|
||||
const result = operation(data);
|
||||
console.log(`${operation} 输出:`, {
|
||||
result: result,
|
||||
resultType: typeof result,
|
||||
resultLength: result ? result.length : 0
|
||||
});
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(`${operation} 失败:`, {
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. 存储问题
|
||||
|
||||
**问题症状**:
|
||||
- 数据丢失
|
||||
- 解析失败
|
||||
- 类型不匹配
|
||||
|
||||
**诊断步骤**:
|
||||
1. 检查 localStorage 状态
|
||||
2. 验证数据序列化
|
||||
3. 确认默认值处理
|
||||
4. 监控存储容量
|
||||
|
||||
```javascript
|
||||
// 调试存储操作
|
||||
function debugStorageOperation(operation, key, value) {
|
||||
console.log(`存储操作: ${operation}`, {
|
||||
key: key,
|
||||
value: value,
|
||||
storageSize: localStorage.length,
|
||||
storageKeys: Object.keys(localStorage)
|
||||
});
|
||||
|
||||
try {
|
||||
const result = operation(key, value);
|
||||
console.log(`存储结果:`, {
|
||||
key: key,
|
||||
storedValue: localStorage.getItem(key),
|
||||
parsedValue: Common.parseJSON(localStorage.getItem(key))
|
||||
});
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(`存储失败:`, {
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 调试工具使用示例
|
||||
|
||||
#### 1. 浏览器控制台调试
|
||||
|
||||
```javascript
|
||||
// 快速测试函数
|
||||
function testFunction() {
|
||||
// 设置断点
|
||||
debugger;
|
||||
|
||||
// 检查当前状态
|
||||
console.log('当前配置:', GlobalConfig.getConfig());
|
||||
console.log('用户信息:', {
|
||||
token: Storage.getUserToken(),
|
||||
encryptBody: Storage.getEncryptBody()
|
||||
});
|
||||
|
||||
// 执行测试
|
||||
return TsCommon.isEmpty('');
|
||||
}
|
||||
|
||||
// 执行测试
|
||||
testFunction();
|
||||
```
|
||||
|
||||
#### 2. Node.js 调试会话
|
||||
|
||||
```javascript
|
||||
// 创建调试脚本
|
||||
const debugScript = async () => {
|
||||
console.log('开始调试会话');
|
||||
|
||||
// 设置断点
|
||||
debugger;
|
||||
|
||||
// 测试加密功能
|
||||
const testData = {message: 'Hello World'};
|
||||
const encrypted = TsCrypto.encrypt(JSON.stringify(testData));
|
||||
const decrypted = TsCrypto.decrypt(encrypted);
|
||||
|
||||
console.log('加密测试:', {
|
||||
original: testData,
|
||||
encrypted: encrypted,
|
||||
decrypted: JSON.parse(decrypted)
|
||||
});
|
||||
|
||||
// 测试网络请求
|
||||
try {
|
||||
const response = await TsHttpUtil.get('/api/test');
|
||||
console.log('网络请求测试:', response);
|
||||
} catch (error) {
|
||||
console.error('网络请求失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
debugScript();
|
||||
```
|
||||
|
||||
#### 3. 性能分析
|
||||
|
||||
```javascript
|
||||
// 性能基准测试
|
||||
function performanceBenchmark() {
|
||||
const iterations = 1000;
|
||||
const testData = 'Test data for encryption'.repeat(100);
|
||||
|
||||
console.time('批量加密');
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
TsCrypto.encrypt(testData);
|
||||
}
|
||||
console.timeEnd('批量加密');
|
||||
|
||||
console.time('批量解密');
|
||||
const encryptedData = TsCrypto.encrypt(testData);
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
TsCrypto.decrypt(encryptedData);
|
||||
}
|
||||
console.timeEnd('批量解密');
|
||||
}
|
||||
|
||||
performanceBenchmark();
|
||||
```
|
||||
|
||||
**章节来源**
|
||||
- [TsHttpUtil.js:99-134](file://src/https/TsHttpUtil.js#L99-L134)
|
||||
- [TsCrypto.js:19-30](file://src/utils/TsCrypto.js#L19-L30)
|
||||
- [TsStorage.js:31-43](file://src/utils/TsStorage.js#L31-L43)
|
||||
|
||||
## 最佳实践总结
|
||||
|
||||
### 系统性调试方法
|
||||
|
||||
#### 1. 分层调试策略
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Problem[问题出现] --> Identify[识别问题类型]
|
||||
Identify --> Isolate[隔离问题范围]
|
||||
Isolate --> Test[测试最小复现]
|
||||
Test --> Debug[深入调试]
|
||||
Debug --> Fix[修复问题]
|
||||
Fix --> Verify[验证修复]
|
||||
Verify --> Monitor[持续监控]
|
||||
Identify --> |网络问题| NetworkDebug[网络调试]
|
||||
Identify --> |加密问题| CryptoDebug[加密调试]
|
||||
Identify --> |存储问题| StorageDebug[存储调试]
|
||||
Identify --> |性能问题| PerfDebug[性能调试]
|
||||
NetworkDebug --> Test
|
||||
CryptoDebug --> Test
|
||||
StorageDebug --> Test
|
||||
PerfDebug --> Test
|
||||
```
|
||||
|
||||
#### 2. 调试工具组合使用
|
||||
|
||||
**多工具协同调试**:
|
||||
- 浏览器开发者工具 + Node.js 调试器
|
||||
- 控制台日志 + 断点调试
|
||||
- 性能分析 + 内存监控
|
||||
- 错误追踪 + 堆栈分析
|
||||
|
||||
#### 3. 调试效率提升技巧
|
||||
|
||||
**快速定位问题**:
|
||||
- 使用条件断点减少调试时间
|
||||
- 实施渐进式调试策略
|
||||
- 建立标准化的调试流程
|
||||
- 维护调试知识库
|
||||
|
||||
**调试报告模板**:
|
||||
|
||||
```markdown
|
||||
# 调试报告
|
||||
|
||||
## 问题描述
|
||||
- 问题现象:
|
||||
- 影响范围:
|
||||
- 复现频率:
|
||||
|
||||
## 调试过程
|
||||
- 关键断点位置:
|
||||
- 观察到的异常行为:
|
||||
- 相关日志信息:
|
||||
|
||||
## 根因分析
|
||||
- 问题原因:
|
||||
- 影响因素:
|
||||
- 代码路径:
|
||||
|
||||
## 解决方案
|
||||
- 临时修复:
|
||||
- 永久解决方案:
|
||||
- 预防措施:
|
||||
|
||||
## 验证结果
|
||||
- 修复验证:
|
||||
- 回归测试:
|
||||
- 性能影响:
|
||||
```
|
||||
|
||||
### 调试工具配置建议
|
||||
|
||||
#### 1. 开发环境配置
|
||||
|
||||
```javascript
|
||||
// 开发环境调试配置
|
||||
const devConfig = {
|
||||
enableLogging: true,
|
||||
logLevel: 'debug',
|
||||
enableBreakpoints: true,
|
||||
autoReload: true,
|
||||
verboseErrors: true
|
||||
};
|
||||
|
||||
// 生产环境调试配置
|
||||
const prodConfig = {
|
||||
enableLogging: false,
|
||||
logLevel: 'error',
|
||||
enableBreakpoints: false,
|
||||
autoReload: false,
|
||||
verboseErrors: false
|
||||
};
|
||||
```
|
||||
|
||||
#### 2. 调试工具推荐
|
||||
|
||||
**必备工具**:
|
||||
- 浏览器开发者工具
|
||||
- VS Code 调试器
|
||||
- Node.js Inspector
|
||||
- Chrome DevTools
|
||||
- Postman/Fiddler
|
||||
|
||||
**高级工具**:
|
||||
- Performance Profiler
|
||||
- Memory Profiler
|
||||
- Network Monitor
|
||||
- Console Logger
|
||||
|
||||
通过遵循这些调试工具和方法指南,开发者可以更高效地诊断和解决基于该 npm 工具包的各种问题,提高开发效率和代码质量。
|
||||
1426
.qoder/repowiki/zh/content/故障排除/配置问题.md
Normal file
1426
.qoder/repowiki/zh/content/故障排除/配置问题.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user