You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
3 days ago | |
|---|---|---|
| .. | ||
| API.md | 3 days ago | |
| FLOW.md | 3 days ago | |
| PROVIDERS.md | 3 days ago | |
| README.md | 3 days ago | |
README.md
OAuth2 使用指南
创建日期:2026-05-26
概述
OAuth2 模块提供基于 OAuth2.0 协议的第三方登录认证功能,支持多种 Provider(如 GitHub、Google),采用模块化设计,易于扩展。
主要功能:
- 第三方账号登录(新用户自动注册)
- 已有账号绑定第三方账号
- 账号解绑
- 多 Provider 支持
快速开始
1. 配置环境变量
# .env
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
2. GitHub 开发者应用申请
- 访问 GitHub Developer Settings
- 点击 "New OAuth App"
- 填写信息:
- Application name: 你的应用名称
- Homepage URL:
http://localhost:3000 - Authorization callback URL:
http://localhost:3000/api/auth/oauth/github/callback
- 点击 "Register application"
- 复制
Client ID - 生成
Client Secret
3. 前端集成
登录按钮
在登录页面添加 GitHub 登录按钮:
<template>
<div class="login-page">
<!-- 原有登录表单 -->
<LoginForm />
<!-- 分割线 -->
<div class="divider">
<span>或</span>
</div>
<!-- GitHub 登录按钮 -->
<button @click="loginWithGithub" class="btn-github">
<Icon name="github" /> GitHub 登录
</button>
</div>
</template>
<script setup>
function loginWithGithub() {
window.location.href = '/api/auth/oauth/github/authorize';
}
</script>
处理回调
登录页或 Profile 页需要处理回调参数:
<script setup>
const router = useRouter();
onMounted(() => {
const url = new URL(window.location.href);
if (url.searchParams.get('oauth_success') === '1') {
// 刷新用户状态
refreshSession();
router.push('/');
}
if (url.searchParams.get('bind_success') === '1') {
// 刷新绑定列表
fetchBindings();
}
if (url.searchParams.get('oauth_error')) {
const error = url.searchParams.get('oauth_error');
console.error('OAuth error:', error);
}
});
</script>
账号绑定(已登录用户)
在用户个人中心页面添加绑定入口:
<script setup>
// 获取绑定列表
const { data: bindingsData } = await useFetch('/api/auth/oauth/bindings');
const bindings = bindingsData.value?.bindings ?? [];
// 解绑操作
async function unbindGithub() {
await $fetch('/api/auth/oauth/github/unbind', { method: 'DELETE' });
await refreshBindings();
}
</script>
<template>
<div class="bindings-list">
<h3>已绑定的账号</h3>
<div v-for="binding in bindings" :key="binding.id" class="binding-item">
<Icon :name="binding.provider" />
<span>{{ binding.username || binding.email }}</span>
<button @click="unbind(binding.provider)">解绑</button>
</div>
<button @click="loginWithGithub" class="btn-github">
<Icon name="github" /> 绑定 GitHub
</button>
</div>
</template>
API 接口
详细 API 文档请参考 API.md
| 接口 | 说明 |
|---|---|
GET /api/auth/oauth/:provider/authorize |
发起 OAuth 授权 |
GET /api/auth/oauth/:provider/callback |
Provider 回调处理 |
POST /api/auth/oauth/bind |
绑定 OAuth 账号 |
DELETE /api/auth/oauth/:provider/unbind |
解绑 OAuth 账号 |
GET /api/auth/oauth/bindings |
获取绑定列表 |
GET /api/auth/oauth/:provider/status |
查询绑定状态 |
流程图详解
详细流程图请参考设计文档 2026-05-26-oauth2-design.md
新用户登录流程
用户点击登录
↓
后端生成 state 并重定向到 GitHub
↓
用户在 GitHub 授权页面确认
↓
GitHub 回调后端 /callback 接口
↓
后端验证 state、用 code 换 token、获取用户信息
↓
后端查找或创建用户、创建 session
↓
重定向到前端页面带上成功参数
↓
前端刷新状态显示登录成功
已登录用户绑定流程
用户在个人中心点击"绑定 GitHub"
↓
后端生成带 userId 的 binding state
↓
重定向到 GitHub 授权页面
↓
用户在 GitHub 授权页面确认
↓
GitHub 回调后端
↓
后端验证 binding state、插入 oauth_accounts 表
↓
重定向到个人中心带上成功参数
↓
前端刷新绑定列表
安全说明
- state 令牌 — 每次授权生成随机 state,防止 CSRF 攻击,5 分钟过期
- Token 安全 — access_token 只在后端流转,不暴露给浏览器
- Session 安全 — 使用 HttpOnly Cookie,防止 XSS 攻击
- 唯一约束 —
provider + provider_user_id联合唯一索引,防止重复绑定
常见问题
Q: GitHub 登录需要哪些权限?
A: 需要 read:user(获取用户信息)和 user:email(获取邮箱)权限。
Q: 用户邮箱未验证怎么办?
A: GitHub 用户可以设置不公开邮箱,此时 email 字段可能为空。建议引导用户补充邮箱绑定。
Q: 如何添加新的 OAuth Provider?
A: 参考 PROVIDERS.md 文档,只需配置即可添加新 Provider。
Q: OAuth 回调 URL 可以自定义吗?
A: 可以通过 redirect_uri 查询参数传递自定义回调地址,但需该地址已在 Provider 配置的白名单中。