388 lines
8.8 KiB
Markdown
388 lines
8.8 KiB
Markdown
|
|
# OAuth 社交登录集成指南
|
|||
|
|
|
|||
|
|
## 概述
|
|||
|
|
|
|||
|
|
系统已完整实现6个主流社交平台的OAuth登录功能,支持用户通过第三方账号快速登录系统。
|
|||
|
|
|
|||
|
|
## 支持的社交平台
|
|||
|
|
|
|||
|
|
| 平台 | 状态 | OAuth版本 | 文档 |
|
|||
|
|
|------|------|----------|------|
|
|||
|
|
| 微信 (WeChat) | ✅ 完整实现 | OAuth 2.0 | [文档](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN) |
|
|||
|
|
| QQ | ✅ 完整实现 | OAuth 2.0 | [文档](https://wiki.connect.qq.com/) |
|
|||
|
|
| 微博 (Weibo) | ✅ 完整实现 | OAuth 2.0 | [文档](https://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6%E8%AF%B4%E6%98%8E) |
|
|||
|
|
| Google | ✅ 完整实现 | OAuth 2.0 | [文档](https://developers.google.com/identity/protocols/oauth2) |
|
|||
|
|
| Facebook | ✅ 完整实现 | OAuth 2.0 | [文档](https://developers.facebook.com/docs/facebook-login/) |
|
|||
|
|
| Twitter | ✅ 完整实现 | OAuth 2.0 | [文档](https://developer.twitter.com/en/docs/authentication/oauth-2-0) |
|
|||
|
|
|
|||
|
|
## 快速开始
|
|||
|
|
|
|||
|
|
### 1. 配置OAuth凭证
|
|||
|
|
|
|||
|
|
将 `configs/oauth_config.example.yaml` 复制为 `configs/oauth_config.yaml`:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cp configs/oauth_config.example.yaml configs/oauth_config.yaml
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 填入OAuth凭证
|
|||
|
|
|
|||
|
|
编辑 `configs/oauth_config.yaml`,填入各平台的真实凭证:
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
# 示例:微信配置
|
|||
|
|
wechat:
|
|||
|
|
enabled: true
|
|||
|
|
app_id: "wx1234567890abcdef"
|
|||
|
|
app_secret: "1234567890abcdef1234567890abcdef"
|
|||
|
|
|
|||
|
|
# 示例:Google配置
|
|||
|
|
google:
|
|||
|
|
enabled: true
|
|||
|
|
client_id: "123456789-abcdef.apps.googleusercontent.com"
|
|||
|
|
client_secret: "GOCSPX-abcdef123456"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 数据库迁移
|
|||
|
|
|
|||
|
|
运行SQL迁移脚本:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
sqlite3 data/users.db < migrations/003_add_social_accounts.sql
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 启动服务
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
go run cmd/server/main.go
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## API接口
|
|||
|
|
|
|||
|
|
### 获取已启用的OAuth提供商
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /api/v1/auth/oauth/providers
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
响应:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"data": [
|
|||
|
|
{
|
|||
|
|
"provider": "wechat",
|
|||
|
|
"enabled": true,
|
|||
|
|
"auth_url": "https://open.weixin.qq.com/connect/qrconnect",
|
|||
|
|
"scopes": ["snsapi_userinfo"]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"provider": "google",
|
|||
|
|
"enabled": true,
|
|||
|
|
"auth_url": "https://accounts.google.com/o/oauth2/v2/auth",
|
|||
|
|
"scopes": ["openid", "email", "profile"]
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 获取OAuth授权URL
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /api/v1/auth/oauth/:provider?state=xxx
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
参数:
|
|||
|
|
- `provider`: 提供商类型 (wechat, qq, weibo, google, facebook, twitter)
|
|||
|
|
- `state`: 可选,用于防止CSRF攻击
|
|||
|
|
|
|||
|
|
响应:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"data": {
|
|||
|
|
"auth_url": "https://open.weixin.qq.com/connect/qrconnect?appid=xxx&redirect_uri=xxx&state=xxx",
|
|||
|
|
"state": "random_state_string"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### OAuth回调处理
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /api/v1/auth/oauth/callback/:provider?code=xxx&state=xxx
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
参数:
|
|||
|
|
- `provider`: 提供商类型
|
|||
|
|
- `code`: OAuth授权码
|
|||
|
|
- `state`: 状态参数(必须与获取授权URL时返回的一致)
|
|||
|
|
|
|||
|
|
响应:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"data": {
|
|||
|
|
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|||
|
|
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|||
|
|
"expires_in": 7200,
|
|||
|
|
"user": {
|
|||
|
|
"id": 1,
|
|||
|
|
"username": "user_abc12345",
|
|||
|
|
"nickname": "张三",
|
|||
|
|
"avatar": "https://thirdwx.qlogo.cn/...",
|
|||
|
|
"email": "user@example.com"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 绑定社交账号
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
POST /api/v1/users/me/bind-social
|
|||
|
|
Authorization: Bearer <access_token>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
请求体:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"provider": "wechat",
|
|||
|
|
"open_id": "oABC1234567890"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 解绑社交账号
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
DELETE /api/v1/users/me/bind-social/:provider
|
|||
|
|
Authorization: Bearer <access_token>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 获取已绑定的社交账号
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
GET /api/v1/users/me/social-accounts
|
|||
|
|
Authorization: Bearer <access_token>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
响应:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"data": [
|
|||
|
|
{
|
|||
|
|
"id": 1,
|
|||
|
|
"provider": "wechat",
|
|||
|
|
"nickname": "张三",
|
|||
|
|
"avatar": "https://thirdwx.qlogo.cn/...",
|
|||
|
|
"status": 1,
|
|||
|
|
"created_at": "2026-03-12T10:00:00Z"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"id": 2,
|
|||
|
|
"provider": "google",
|
|||
|
|
"nickname": "John Doe",
|
|||
|
|
"avatar": "https://lh3.googleusercontent.com/...",
|
|||
|
|
"status": 1,
|
|||
|
|
"created_at": "2026-03-12T11:00:00Z"
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 登录流程
|
|||
|
|
|
|||
|
|
### 1. 新用户首次登录
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
用户点击"微信登录"
|
|||
|
|
↓
|
|||
|
|
前端调用 GET /api/v1/auth/oauth/wechat
|
|||
|
|
↓
|
|||
|
|
后端返回微信授权URL
|
|||
|
|
↓
|
|||
|
|
用户在微信扫码授权
|
|||
|
|
↓
|
|||
|
|
微信回调到 /api/v1/auth/oauth/callback/wechat
|
|||
|
|
↓
|
|||
|
|
后端创建新用户(自动激活)
|
|||
|
|
↓
|
|||
|
|
后端创建社交账号绑定记录
|
|||
|
|
↓
|
|||
|
|
返回JWT令牌
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 已绑定用户登录
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
用户点击"微信登录"
|
|||
|
|
↓
|
|||
|
|
前端调用 GET /api/v1/auth/oauth/wechat
|
|||
|
|
↓
|
|||
|
|
后端返回微信授权URL
|
|||
|
|
↓
|
|||
|
|
用户在微信扫码授权
|
|||
|
|
↓
|
|||
|
|
微信回调到 /api/v1/auth/oauth/callback/wechat
|
|||
|
|
↓
|
|||
|
|
后端找到已绑定的用户账号
|
|||
|
|
↓
|
|||
|
|
返回JWT令牌
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 自动合并账号
|
|||
|
|
|
|||
|
|
如果社交登录返回的邮箱与现有用户邮箱相同,系统会自动将社交账号绑定到该用户。
|
|||
|
|
|
|||
|
|
## 各平台配置指南
|
|||
|
|
|
|||
|
|
### 微信 (WeChat)
|
|||
|
|
|
|||
|
|
1. 访问 [微信开放平台](https://open.weixin.qq.com/)
|
|||
|
|
2. 创建网站应用
|
|||
|
|
3. 获取 AppID 和 AppSecret
|
|||
|
|
4. 设置回调域名
|
|||
|
|
|
|||
|
|
### QQ
|
|||
|
|
|
|||
|
|
1. 访问 [QQ互联](https://connect.qq.com/)
|
|||
|
|
2. 创建应用
|
|||
|
|
3. 获取 App ID 和 App Key
|
|||
|
|
4. 设置回调地址
|
|||
|
|
|
|||
|
|
### 微博 (Weibo)
|
|||
|
|
|
|||
|
|
1. 访问 [微博开放平台](https://open.weibo.com/)
|
|||
|
|
2. 创建应用
|
|||
|
|
3. 获取 App Key 和 App Secret
|
|||
|
|
4. 设置回调URL
|
|||
|
|
|
|||
|
|
### Google
|
|||
|
|
|
|||
|
|
1. 访问 [Google Cloud Console](https://console.cloud.google.com/)
|
|||
|
|
2. 创建项目
|
|||
|
|
3. 启用 Google+ API
|
|||
|
|
4. 创建 OAuth 2.0 客户端ID
|
|||
|
|
5. 获取 Client ID 和 Client Secret
|
|||
|
|
6. 添加授权重定向URI
|
|||
|
|
|
|||
|
|
### Facebook
|
|||
|
|
|
|||
|
|
1. 访问 [Facebook for Developers](https://developers.facebook.com/)
|
|||
|
|
2. 创建应用
|
|||
|
|
3. 启用 Facebook Login
|
|||
|
|
4. 获取 App ID 和 App Secret
|
|||
|
|
5. 配置 OAuth 重定向URI
|
|||
|
|
|
|||
|
|
### Twitter
|
|||
|
|
|
|||
|
|
1. 访问 [Twitter Developer Portal](https://developer.twitter.com/)
|
|||
|
|
2. 创建应用
|
|||
|
|
3. 启用 OAuth 2.0
|
|||
|
|
4. 获取 Client ID 和 Client Secret
|
|||
|
|
5. 配置回调URL
|
|||
|
|
|
|||
|
|
## 环境变量支持
|
|||
|
|
|
|||
|
|
除了配置文件,也可以通过环境变量配置OAuth:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 微信
|
|||
|
|
WECHAT_OAUTH_ENABLED=true
|
|||
|
|
WECHAT_APP_ID=wx1234567890abcdef
|
|||
|
|
WECHAT_APP_SECRET=1234567890abcdef1234567890abcdef
|
|||
|
|
|
|||
|
|
# Google
|
|||
|
|
GOOGLE_OAUTH_ENABLED=true
|
|||
|
|
GOOGLE_CLIENT_ID=123456789-abcdef.apps.googleusercontent.com
|
|||
|
|
GOOGLE_CLIENT_SECRET=GOCSPX-abcdef123456
|
|||
|
|
|
|||
|
|
# Facebook
|
|||
|
|
FACEBOOK_OAUTH_ENABLED=true
|
|||
|
|
FACEBOOK_APP_ID=123456789
|
|||
|
|
FACEBOOK_APP_SECRET=abcdef123456
|
|||
|
|
|
|||
|
|
# QQ
|
|||
|
|
QQ_OAUTH_ENABLED=true
|
|||
|
|
QQ_APP_ID=123456789
|
|||
|
|
QQ_APP_KEY=abcdef123456
|
|||
|
|
QQ_APP_SECRET=abcdef123456
|
|||
|
|
|
|||
|
|
# 微博
|
|||
|
|
WEIBO_OAUTH_ENABLED=true
|
|||
|
|
WEIBO_APP_KEY=123456789
|
|||
|
|
WEIBO_APP_SECRET=abcdef123456
|
|||
|
|
|
|||
|
|
# Twitter
|
|||
|
|
TWITTER_OAUTH_ENABLED=true
|
|||
|
|
TWITTER_CLIENT_ID=abcdef123456
|
|||
|
|
TWITTER_CLIENT_SECRET=abcdef123456
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 安全注意事项
|
|||
|
|
|
|||
|
|
1. **状态参数验证**: 所有OAuth请求都使用state参数防止CSRF攻击
|
|||
|
|
2. **令牌存储**: Access Token和Refresh Token存储在内存中,不持久化
|
|||
|
|
3. **HTTPS**: 生产环境必须使用HTTPS
|
|||
|
|
4. **回调URL**: 确保回调URL在OAuth提供商处正确配置
|
|||
|
|
5. **凭证管理**: OAuth凭证应存储在安全的位置,不要提交到代码仓库
|
|||
|
|
|
|||
|
|
## 故障排查
|
|||
|
|
|
|||
|
|
### 问题:获取授权URL失败
|
|||
|
|
|
|||
|
|
- 检查配置文件路径是否正确
|
|||
|
|
- 检查OAuth凭证是否填写正确
|
|||
|
|
- 检查提供商是否已启用 (enabled: true)
|
|||
|
|
|
|||
|
|
### 问题:回调处理失败
|
|||
|
|
|
|||
|
|
- 检查回调URL是否在OAuth提供商处正确配置
|
|||
|
|
- 检查授权码是否有效(授权码只能使用一次)
|
|||
|
|
- 检查state参数是否正确
|
|||
|
|
|
|||
|
|
### 问题:无法获取用户信息
|
|||
|
|
|
|||
|
|
- 检查Access Token是否有效
|
|||
|
|
- 检查API权限是否正确配置
|
|||
|
|
- 检查用户是否已授权必要的scope
|
|||
|
|
|
|||
|
|
## 测试
|
|||
|
|
|
|||
|
|
可以使用Postman或curl测试OAuth流程:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 1. 获取授权URL
|
|||
|
|
curl "http://localhost:8080/api/v1/auth/oauth/google"
|
|||
|
|
|
|||
|
|
# 2. 使用返回的auth_url在浏览器中完成授权
|
|||
|
|
|
|||
|
|
# 3. 获取回调后的code和state,然后回调
|
|||
|
|
curl "http://localhost:8080/api/v1/auth/oauth/callback/google?code=xxx&state=xxx"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 代码结构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
internal/
|
|||
|
|
├── auth/
|
|||
|
|
│ ├── oauth.go # OAuth管理器接口和实现
|
|||
|
|
│ ├── oauth_config.go # OAuth配置加载器
|
|||
|
|
│ ├── oauth_utils.go # OAuth工具函数
|
|||
|
|
│ ├── errors.go # OAuth错误定义
|
|||
|
|
│ └── providers/
|
|||
|
|
│ ├── wechat.go # 微信OAuth实现
|
|||
|
|
│ ├── google.go # Google OAuth实现
|
|||
|
|
│ ├── facebook.go # Facebook OAuth实现
|
|||
|
|
│ ├── qq.go # QQ OAuth实现
|
|||
|
|
│ ├── weibo.go # 微博OAuth实现
|
|||
|
|
│ └── twitter.go # Twitter OAuth实现
|
|||
|
|
├── domain/
|
|||
|
|
│ └── social_account.go # 社交账号领域模型
|
|||
|
|
├── repository/
|
|||
|
|
│ └── social_account_repo.go # 社交账号仓库
|
|||
|
|
└── service/
|
|||
|
|
└── auth.go # 认证服务(包含OAuth方法)
|
|||
|
|
```
|