403 lines
7.3 KiB
Markdown
403 lines
7.3 KiB
Markdown
# Top-Fans Gateway 网关服务
|
||
|
||
## 📋 概述
|
||
|
||
Top-Fans Gateway 是一个基于 Gin 框架的 HTTP 网关,负责:
|
||
- 接收客户端 HTTP 请求
|
||
- JWT Token 认证和验证
|
||
- 将 HTTP 请求转换为 Dubbo RPC 调用
|
||
- 通过 Dubbo Attachments 传递用户信息到后端微服务
|
||
|
||
---
|
||
|
||
## 🏗️ 架构
|
||
|
||
```
|
||
客户端 (Mobile/Web)
|
||
↓ HTTP/HTTPS + JWT Token
|
||
Gin Gateway (本服务)
|
||
↓ Dubbo RPC + Attachments
|
||
UserService (Dubbo 微服务)
|
||
↓
|
||
Database
|
||
```
|
||
|
||
---
|
||
|
||
## 📦 安装依赖
|
||
|
||
```bash
|
||
cd backend/gateway
|
||
|
||
# ⚠️ 重要:先配置 Go 代理(避免 TLS 证书错误)
|
||
export GOPROXY=https://goproxy.io,direct
|
||
|
||
# 安装依赖
|
||
go mod tidy
|
||
```
|
||
|
||
**常见问题**:
|
||
- 如果遇到 `tls: failed to verify certificate` 错误,请使用上面的代理配置
|
||
- 可选代理:`https://proxy.golang.org,direct` 或 `https://mirrors.aliyun.com/goproxy/,direct`
|
||
|
||
---
|
||
|
||
## ⚙️ 配置
|
||
|
||
网关通过环境变量配置,支持的环境变量:
|
||
|
||
| 环境变量 | 说明 | 默认值 |
|
||
|---------|------|--------|
|
||
| `SERVER_PORT` | 网关监听端口 | `8080` |
|
||
| `GIN_MODE` | Gin 运行模式 (`debug`, `release`, `test`) | `debug` |
|
||
| `DUBBO_USER_SERVICE_URL` | UserService Dubbo 地址 | `127.0.0.1:20000` |
|
||
| `JWT_SECRET` | JWT 密钥 | `topfans-secret-key-please-change-in-production` |
|
||
|
||
### 配置示例
|
||
|
||
```bash
|
||
# 开发环境
|
||
export SERVER_PORT=8080
|
||
export GIN_MODE=debug
|
||
export DUBBO_USER_SERVICE_URL=127.0.0.1:20000
|
||
|
||
# 生产环境
|
||
export SERVER_PORT=8080
|
||
export GIN_MODE=release
|
||
export DUBBO_USER_SERVICE_URL=prod-userservice:20000
|
||
export JWT_SECRET=your-secure-secret-key
|
||
```
|
||
|
||
---
|
||
|
||
## 🚀 启动服务
|
||
|
||
### 方式 1:直接运行
|
||
|
||
```bash
|
||
cd backend/gateway
|
||
go run main.go
|
||
```
|
||
|
||
### 方式 2:编译后运行
|
||
|
||
```bash
|
||
cd backend/gateway
|
||
go build -o gateway main.go
|
||
./gateway
|
||
```
|
||
|
||
### 方式 3:使用环境变量
|
||
|
||
```bash
|
||
cd backend/gateway
|
||
SERVER_PORT=8080 GIN_MODE=debug go run main.go
|
||
```
|
||
|
||
---
|
||
|
||
## 📡 API 接口
|
||
|
||
### 公开接口(无需认证)
|
||
|
||
#### 1. 健康检查
|
||
```bash
|
||
GET /health
|
||
```
|
||
|
||
#### 2. 用户注册
|
||
```bash
|
||
POST /api/v1/auth/register
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"mobile": "13800000001",
|
||
"password": "password123",
|
||
"star_id": 87,
|
||
"nickname": "测试用户"
|
||
}
|
||
```
|
||
|
||
#### 3. 用户登录
|
||
```bash
|
||
POST /api/v1/auth/login
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"mobile": "13800000001",
|
||
"password": "password123"
|
||
}
|
||
|
||
# 响应
|
||
{
|
||
"base": {...},
|
||
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||
"expiresIn": "86400",
|
||
"user": {...},
|
||
"fanProfile": {...}
|
||
}
|
||
```
|
||
|
||
#### 4. 获取指定用户信息
|
||
```bash
|
||
GET /api/v1/users/:user_id
|
||
```
|
||
|
||
#### 5. 获取粉丝档案
|
||
```bash
|
||
GET /api/v1/fan-profiles?user_id=44&star_id=87
|
||
```
|
||
|
||
#### 6. 获取明星列表
|
||
```bash
|
||
GET /api/v1/fan-identities?keyword=王
|
||
```
|
||
|
||
### 受保护接口(需要认证)
|
||
|
||
**请求头格式**:
|
||
```
|
||
Authorization: Bearer <access_token>
|
||
```
|
||
|
||
#### 1. 获取当前用户信息
|
||
```bash
|
||
GET /api/v1/auth/me
|
||
Authorization: Bearer <token>
|
||
```
|
||
|
||
#### 2. 获取当前用户粉丝档案
|
||
```bash
|
||
GET /api/v1/me/profile
|
||
Authorization: Bearer <token>
|
||
```
|
||
|
||
#### 3. 更新昵称
|
||
```bash
|
||
PUT /api/v1/me/nickname
|
||
Authorization: Bearer <token>
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"nickname": "新昵称"
|
||
}
|
||
```
|
||
|
||
#### 4. 更新密码
|
||
```bash
|
||
POST /api/v1/account/password
|
||
Authorization: Bearer <token>
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"old_password": "password123",
|
||
"new_password": "newpassword456"
|
||
}
|
||
```
|
||
|
||
#### 5. 添加粉丝身份
|
||
```bash
|
||
POST /api/v1/my/fan-identities
|
||
Authorization: Bearer <token>
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"star_id": 88,
|
||
"nickname": "粉丝小红"
|
||
}
|
||
```
|
||
|
||
#### 6. 切换粉丝身份
|
||
```bash
|
||
POST /api/v1/my/fan-identities/switch
|
||
Authorization: Bearer <token>
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"new_star_id": 88
|
||
}
|
||
```
|
||
|
||
#### 7. 刷新 Token
|
||
```bash
|
||
POST /api/v1/auth/refresh
|
||
Authorization: Bearer <token>
|
||
```
|
||
|
||
#### 8. 登出
|
||
```bash
|
||
POST /api/v1/auth/logout
|
||
Authorization: Bearer <token>
|
||
```
|
||
|
||
---
|
||
|
||
## 🧪 测试
|
||
|
||
### 完整测试流程
|
||
|
||
```bash
|
||
# 1. 启动 UserService
|
||
cd backend/services/userService
|
||
go run main.go
|
||
|
||
# 2. 启动 Gateway(新终端)
|
||
cd backend/gateway
|
||
go run main.go
|
||
|
||
# 3. 测试注册
|
||
curl -X POST http://localhost:8080/api/v1/auth/register \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"mobile": "13800000001",
|
||
"password": "password123",
|
||
"star_id": 87,
|
||
"nickname": "测试用户"
|
||
}'
|
||
|
||
# 4. 测试登录
|
||
TOKEN=$(curl -s -X POST http://localhost:8080/api/v1/auth/login \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"mobile": "13800000001",
|
||
"password": "password123"
|
||
}' | jq -r '.accessToken')
|
||
|
||
echo "Token: $TOKEN"
|
||
|
||
# 5. 测试获取当前用户信息(需要认证)
|
||
curl -X GET http://localhost:8080/api/v1/auth/me \
|
||
-H "Authorization: Bearer $TOKEN"
|
||
|
||
# 6. 测试获取粉丝档案
|
||
curl -X GET http://localhost:8080/api/v1/me/profile \
|
||
-H "Authorization: Bearer $TOKEN"
|
||
```
|
||
|
||
---
|
||
|
||
## 📂 项目结构
|
||
|
||
```
|
||
gateway/
|
||
├── main.go # 主入口
|
||
├── go.mod # 依赖管理
|
||
├── README.md # 本文档
|
||
├── config/
|
||
│ └── config.go # 配置管理
|
||
├── middleware/
|
||
│ └── auth_middleware.go # JWT 认证中间件
|
||
├── controller/
|
||
│ ├── auth_controller.go # 认证控制器(登录、注册等)
|
||
│ └── user_controller.go # 用户控制器(需要认证的接口)
|
||
└── router/
|
||
└── router.go # 路由配置
|
||
```
|
||
|
||
---
|
||
|
||
## 🔑 认证流程
|
||
|
||
```
|
||
1. 客户端登录
|
||
POST /api/v1/auth/login
|
||
↓
|
||
2. Gateway 转发到 UserService
|
||
Dubbo RPC: Login()
|
||
↓
|
||
3. UserService 验证用户,生成 JWT
|
||
↓
|
||
4. 返回 accessToken 给客户端
|
||
|
||
5. 客户端访问受保护接口
|
||
GET /api/v1/auth/me
|
||
Header: Authorization: Bearer <token>
|
||
↓
|
||
6. Gateway 认证中间件验证 JWT
|
||
↓
|
||
7. 提取 user_id, star_id
|
||
↓
|
||
8. Gateway 通过 Dubbo Attachments 传递
|
||
ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{
|
||
"user_id": user_id,
|
||
"star_id": star_id,
|
||
})
|
||
↓
|
||
9. UserService 从 Attachments 获取用户信息
|
||
userID := dubbo.GetAttachment(ctx, "user_id")
|
||
↓
|
||
10. 执行业务逻辑,返回结果
|
||
```
|
||
|
||
---
|
||
|
||
## 📝 日志
|
||
|
||
日志文件存储在 `logs/` 目录:
|
||
- `logs/gateway.log` - 网关日志
|
||
|
||
查看日志:
|
||
```bash
|
||
tail -f logs/gateway.log
|
||
```
|
||
|
||
---
|
||
|
||
## ⚠️ 注意事项
|
||
|
||
1. **生产环境必须修改 JWT_SECRET**
|
||
2. **建议使用 HTTPS**
|
||
3. **配置合适的 CORS 策略**
|
||
4. **定期轮换 JWT 密钥**
|
||
5. **监控网关性能和错误率**
|
||
|
||
---
|
||
|
||
## 🐛 常见问题
|
||
|
||
### 1. 连接 Dubbo 服务失败
|
||
|
||
```
|
||
Error: Failed to create Dubbo client
|
||
```
|
||
|
||
**解决方案**:
|
||
- 确保 UserService 正在运行
|
||
- 检查 `DUBBO_USER_SERVICE_URL` 配置是否正确
|
||
- 检查网络连接
|
||
|
||
### 2. Token 验证失败
|
||
|
||
```
|
||
Error: invalid or expired token
|
||
```
|
||
|
||
**解决方案**:
|
||
- 确保 Gateway 和 UserService 使用相同的 JWT_SECRET
|
||
- 检查 Token 是否过期
|
||
- 确认 Token 格式正确(Bearer + 空格 + token)
|
||
|
||
### 3. 端口冲突
|
||
|
||
```
|
||
Error: bind: address already in use
|
||
```
|
||
|
||
**解决方案**:
|
||
- 修改 `SERVER_PORT` 环境变量
|
||
- 或停止占用该端口的其他进程
|
||
|
||
---
|
||
|
||
## 📚 相关文档
|
||
|
||
- [完整测试流程](../services/userService/完整测试流程.md)
|
||
- [网关架构说明](../services/userService/网关架构说明.md)
|
||
- [Proto 定义](../proto/user.proto)
|
||
|
||
---
|
||
|
||
**版本**:v1.0.0
|
||
**最后更新**:2026-01-04
|
||
|