🔴 高优先级 (6项全部完成): - 数据库事务支持 (InsertMessageWithLog) - SQL注入修复 (参数化查询) - 配置验证 (Validate方法) - 会话密钥强化 (长度验证) - 签名验证增强 (SignVerificationResult) - 密码哈希支持 (bcrypt) 🟡 中优先级 (15项全部完成): - 连接池配置 (MaxOpenConns, MaxIdleConns) - 查询优化 (范围查询, 索引) - 健康检查增强 (/health 端点) - API版本控制 (/api/v1/*) - 认证中间件 (RequireAuth, RequireAPIAuth) - 定时任务优化 (robfig/cron) - 配置文件示例 (config.example.yaml) - 常量定义 (config/constants.go) - 开发文档 (DEVELOPMENT.md) 🟢 低优先级 (9项全部完成): - Docker支持 (Dockerfile, docker-compose.yml) - Makefile构建脚本 - 优化报告 (OPTIMIZATION_REPORT.md) - 密码哈希工具 (tools/password_hash.go) - 14个新文件 - 30项优化100%完成 版本: v2.0.0
343 lines
8.0 KiB
Markdown
343 lines
8.0 KiB
Markdown
# SmsReceiver-go 开发文档
|
||
|
||
## 项目概述
|
||
|
||
SmsReceiver-go 是一个用 Go 语言重构的短信接收服务,完全复现 Python 版本功能。
|
||
|
||
### 核心特性
|
||
|
||
- ✅ 基于 Go + SQLite 的轻量级短信接收服务
|
||
- ✅ 支持签名验证(HMAC-SHA256)
|
||
- ✅ 登录认证保护所有页面
|
||
- ✅ Web 管理界面(短信列表、详情、日志、统计)
|
||
- ✅ 支持多 API Token 配置
|
||
- ✅ 时区自动转换
|
||
- ✅ 自动清理旧消息(支持 cron 定时任务)
|
||
|
||
## 技术栈
|
||
|
||
- **Web 框架**: Gorilla Mux
|
||
- **模板引擎**: html/template
|
||
- **数据库**: SQLite3
|
||
- **认证**: gorilla/sessions
|
||
- **定时任务**: robfig/cron
|
||
- **配置管理**: viper
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
SmsReceiver-go/
|
||
├── main.go # 入口文件
|
||
├── config.yaml # 配置文件
|
||
├── sms-receiver-v2 # 编译后的二进制文件
|
||
├── sms_receiver_go.db # 独立数据库
|
||
├── auth/ # 认证模块
|
||
│ ├── auth.go # 认证逻辑
|
||
│ └── password.go # 密码验证
|
||
├── config/ # 配置模块
|
||
│ ├── config.go # 配置加载
|
||
│ └── constants.go # 常量定义
|
||
├── database/ # 数据库模块
|
||
│ └── database.go # 数据库操作
|
||
├── handlers/ # HTTP 处理器
|
||
│ ├── handlers.go # 主处理函数
|
||
│ ├── middleware.go # 中间件
|
||
│ └── health.go # 健康检查
|
||
├── models/ # 数据模型
|
||
│ └── message.go # 数据结构定义
|
||
├── sign/ # 签名验证
|
||
│ └── sign.go # HMAC-SHA256 签名
|
||
├── static/ # 静态资源
|
||
├── templates/ # HTML 模板
|
||
└── tools/ # 工具脚本
|
||
└── password_hash.go # 密码哈希生成工具
|
||
```
|
||
|
||
## 数据库设计
|
||
|
||
### sms_messages 表
|
||
存储接收到的短信消息:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | INTEGER | 主键,自增 |
|
||
| from_number | TEXT | 发送方号码 |
|
||
| content | TEXT | 短信内容 |
|
||
| timestamp | INTEGER | 短信时间戳(毫秒级) |
|
||
| device_info | TEXT | 设备信息(可选) |
|
||
| sim_info | TEXT | SIM 信息(可选) |
|
||
| sign_verified | INTEGER | 签名验证结果(0/1) |
|
||
| ip_address | TEXT | 客户端 IP |
|
||
| created_at | TIMESTAMP | 创建时间 |
|
||
|
||
### receive_logs 表
|
||
存储短信接收日志:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | INTEGER | 主键,自增 |
|
||
| from_number | TEXT | 发送方号码 |
|
||
| content | TEXT | 短信内容 |
|
||
| timestamp | INTEGER | 短信时间戳(毫秒级) |
|
||
| sign | TEXT | 签名值(可选) |
|
||
| sign_valid | INTEGER | 签名验证结果(0/1) |
|
||
| ip_address | TEXT | 客户端 IP |
|
||
| status | TEXT | 状态(success/error) |
|
||
| error_message | TEXT | 错误信息(可选) |
|
||
| created_at | TIMESTAMP | 创建时间 |
|
||
|
||
## API 接口
|
||
|
||
### 1. 接收短信
|
||
|
||
**请求**: `POST /api/receive`
|
||
|
||
**参数**:
|
||
- `from` (必需): 发送方号码
|
||
- `content` (必需): 短信内容
|
||
- `timestamp`: 短信时间戳(毫秒级,可选,默认当前时间)
|
||
- `sign`: 签名值(可选,根据配置验证)
|
||
- `token`: API Token(可选,用于签名验证)
|
||
- `device`: 设备信息(可选)
|
||
- `sim`: SIM 信息(可选)
|
||
|
||
**响应**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "短信已接收",
|
||
"message_id": 123
|
||
}
|
||
```
|
||
|
||
### 2. 获取消息列表
|
||
|
||
**请求**: `GET /api/messages?page=1&limit=20&from=...&search=...`
|
||
|
||
**参数**:
|
||
- `page`: 页码(从1开始)
|
||
- `limit`: 每页数量(最大100)
|
||
- `from`: 发送方号码筛选
|
||
- `search`: 内容或号码搜索
|
||
|
||
**响应**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": [
|
||
{
|
||
"id": 123,
|
||
"from_number": "+8613800138000",
|
||
"content": "短信内容",
|
||
"timestamp": 1704567890123,
|
||
"timestamp_str": "2024-01-07 12:34:50"
|
||
}
|
||
],
|
||
"total": 100,
|
||
"page": 1,
|
||
"limit": 20
|
||
}
|
||
```
|
||
|
||
### 3. 获取统计信息
|
||
|
||
**请求**: `GET /api/statistics`
|
||
|
||
**响应**:
|
||
```json
|
||
{
|
||
"success": true,
|
||
"data": {
|
||
"total": 100,
|
||
"today": 10,
|
||
"week": 50,
|
||
"verified": 80,
|
||
"unverified": 20
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4. 健康检查
|
||
|
||
**请求**: `GET /health`
|
||
|
||
**响应**:
|
||
```json
|
||
{
|
||
"status": "ok",
|
||
"app_name": "SmsReceiver-go",
|
||
"version": "2.0.0",
|
||
"database": "ok",
|
||
"total_messages": 100,
|
||
"uptime": "1h23m45s"
|
||
}
|
||
```
|
||
|
||
## 部署指南
|
||
|
||
### 1. 编译
|
||
|
||
```bash
|
||
cd /root/.openclaw/workspace/SmsReceiver-go
|
||
go build -o sms-receiver-v2 main.go
|
||
```
|
||
|
||
### 2. 配置
|
||
|
||
```bash
|
||
# 复制配置示例
|
||
cp config.example.yaml config.yaml
|
||
|
||
# 编辑配置
|
||
vim config.yaml
|
||
```
|
||
|
||
### 3. 生成密码哈希(可选)
|
||
|
||
```bash
|
||
# 生成 bcrypt 哈希(推荐)
|
||
go run tools/password_hash.go your_password
|
||
|
||
# 将输出复制到 config.yaml 的 security.password_hash
|
||
```
|
||
|
||
### 4. 运行
|
||
|
||
```bash
|
||
# 直接运行
|
||
./sms-receiver-v2
|
||
|
||
# 或指定配置文件
|
||
./sms-receiver-v2 -config /path/to/config.yaml
|
||
```
|
||
|
||
### 5. Systemd 服务
|
||
|
||
创建 `/etc/systemd/system/sms-receiver-go.service`:
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=SmsReceiver-go SMS Service
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=root
|
||
WorkingDirectory=/root/.openclaw/workspace/SmsReceiver-go
|
||
ExecStart=/root/.openclaw/workspace/SmsReceiver-go/sms-receiver-v2
|
||
Restart=on-failure
|
||
RestartSec=5
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
管理服务:
|
||
```bash
|
||
systemctl daemon-reload
|
||
systemctl enable sms-receiver-go
|
||
systemctl start sms-receiver-go
|
||
systemctl status sms-receiver-go
|
||
```
|
||
|
||
## 管理脚本
|
||
|
||
`sms-receiver-go-ctl.sh` 提供便捷的管理命令:
|
||
|
||
```bash
|
||
./sms-receiver-go-ctl.sh start # 启动服务
|
||
./sms-receiver-go-ctl.sh stop # 停止服务
|
||
./sms-receiver-go-ctl.sh restart # 重启服务
|
||
./sms-receiver-go-ctl.sh status # 查看状态
|
||
./sms-receiver-go-ctl.sh log # 查看日志
|
||
./sms-receiver-go-ctl.sh logtail # 实时查看日志
|
||
```
|
||
|
||
## 开发说明
|
||
|
||
### 时间戳说明
|
||
|
||
- `timestamp` 字段:毫秒级时间戳(uint64)
|
||
- `created_at` 字段:SQLite TIMESTAMP(秒级精度)
|
||
- 模板中显示使用 `timestamp` 字段(更准确)
|
||
|
||
### 会话管理
|
||
|
||
- 使用 `gorilla/sessions` 管理会话
|
||
- 会话默认有效期 1 小时(可配置)
|
||
- 密钥至少 16 字节
|
||
|
||
### 签名验证
|
||
|
||
签名生成规则(HMAC-SHA256):
|
||
```
|
||
stringToSign = timestamp + "\n" + secret
|
||
signature = base64(hmac_sha256(stringToSign, secret))
|
||
```
|
||
|
||
Go 实现示例:
|
||
```go
|
||
stringToSign := strconv.FormatInt(timestamp, 10) + "\n" + secret
|
||
hmacCode := hmac.New(sha256.New, []byte(secret))
|
||
hmacCode.Write([]byte(stringToSign))
|
||
signBytes := hmacCode.Sum(nil)
|
||
signBase64 := base64.StdEncoding.EncodeToString(signBytes)
|
||
sign := url.QueryEscape(signBase64)
|
||
```
|
||
|
||
### 数据库事务
|
||
|
||
接收短信时使用事务确保数据一致性:
|
||
- 同时插入消息和日志
|
||
- 任一失败则整体回滚
|
||
|
||
### 查询优化
|
||
|
||
- 使用索引优化查询速度
|
||
- 统计查询使用范围查询而非函数调用
|
||
- 定期优化数据库:`VACUUM ANALYZE`
|
||
|
||
## 常见问题
|
||
|
||
### 1. 统计数据不显示?
|
||
|
||
检查数据库查询是否正确,重点关注时间范围计算逻辑。
|
||
|
||
### 2. 签名验证失败?
|
||
|
||
- 检查 token 配置是否正确
|
||
- 验证时间戳是否在有效期内
|
||
- 确认签名生成算法与服务器一致
|
||
|
||
### 3. 数据库连接失败?
|
||
|
||
- 检查数据库文件路径是否正确
|
||
- 确认文件权限(读写权限)
|
||
- 检查磁盘空间
|
||
|
||
### 4. 如何清空所有数据?
|
||
|
||
```bash
|
||
# 停止服务
|
||
systemctl stop sms-receiver-go
|
||
|
||
# 删除数据库
|
||
rm sms_receiver_go.db
|
||
|
||
# 重启服务(会自动重建数据库)
|
||
systemctl start sms-receiver-go
|
||
```
|
||
|
||
## 安全建议
|
||
|
||
1. **使用强密码**:建议至少12位,包含大小写字母、数字和特殊符号
|
||
2. **使用密码哈希**:运行 `tools/password_hash.go` 生成 bcrypt 哈希
|
||
3. **配置签名验证**:启用 `sign_verify` 并为每个 token 配置 secret
|
||
4. **限制访问**:通过防火墙或反向代理限制访问
|
||
5. **定期备份**:定期备份数据库文件 `sms_receiver_go.db`
|
||
6. **更新依赖**:定期更新 go 依赖包:`go get -u ./...`
|
||
|
||
## 许可证
|
||
|
||
MIT License
|