OAUTH_LOGIN_TEST_GUIDE.md 7.7 KB

OAuth 单点登录测试指南

概述

OAuth 2.0 单点登录已成功集成到标注平台!现在可以使用 SSO 认证中心进行登录。

配置信息

后端配置 (backend/config.yaml)

oauth:
  enabled: true
  base_url: "http://192.168.92.61:8000"
  client_id: "sRyfcQwNVoFimigzuuZxhqd36fPkVN5G"
  client_secret: "96RuKb4obAn9bQ9i5NtINiKBMvF_9uuCR7eNzD9dWQMbOWZaV3P593-8yLOqzWRd"
  redirect_uri: "http://localhost:4200/auth/callback"
  scope: "profile email"

OAuth 端点

  • 授权端点: http://192.168.92.61:8000/oauth/authorize
  • 令牌端点: http://192.168.92.61:8000/oauth/token
  • 用户信息端点: http://192.168.92.61:8000/oauth/userinfo

测试步骤

1. 启动服务

后端:

cd backend
python main.py

前端:

cd web
yarn start lq_label

2. 访问登录页面

打开浏览器访问: http://localhost:4200/login

3. 使用 OAuth 登录

  1. 点击 "使用 SSO 登录" 按钮
  2. 浏览器会重定向到 OAuth 认证中心 (http://192.168.92.61:8000)
  3. 在 SSO 登录页面输入用户名和密码
  4. 授权后,浏览器会重定向回标注平台 (http://localhost:4200/auth/callback)
  5. 系统自动完成登录,跳转到首页

4. 验证登录状态

登录成功后,你应该能看到:

  • 右上角显示用户名和头像
  • 可以访问所有受保护的页面(项目、任务、标注等)
  • 用户菜单显示用户信息和"退出登录"按钮

OAuth 登录流程

1. 用户点击"使用 SSO 登录"
   ↓
2. 前端调用 /api/oauth/login 获取授权 URL 和 state
   ↓
3. 前端保存 state 到 sessionStorage
   ↓
4. 前端重定向到 OAuth 授权页面
   ↓
5. 用户在 SSO 登录并授权
   ↓
6. OAuth 重定向回 /auth/callback?code=xxx&state=yyy
   ↓
7. 前端验证 state 参数
   ↓
8. 前端调用 /api/oauth/callback 用 code 换取 token
   ↓
9. 后端用 code 向 OAuth 换取 access_token
   ↓
10. 后端用 access_token 获取用户信息
   ↓
11. 后端同步用户到本地数据库
   ↓
12. 后端生成本地 JWT tokens
   ↓
13. 前端保存 tokens 和用户信息
   ↓
14. 前端跳转到首页

API 端点

后端 OAuth API

端点 方法 描述
/api/oauth/login GET 获取授权 URL 和 state
/api/oauth/callback GET 处理 OAuth 回调,换取 token
/api/oauth/status GET 获取 OAuth 配置状态

示例请求

获取授权 URL:

curl http://localhost:8000/api/oauth/login

响应:

{
  "authorization_url": "http://192.168.92.61:8000/oauth/authorize?response_type=code&client_id=sRyfcQwNVoFimigzuuZxhqd36fPkVN5G&redirect_uri=http://localhost:4200/auth/callback&scope=profile+email&state=xxx",
  "state": "xxx"
}

处理回调:

curl "http://localhost:8000/api/oauth/callback?code=xxx&state=yyy"

响应:

{
  "access_token": "eyJ...",
  "refresh_token": "eyJ...",
  "token_type": "bearer",
  "user": {
    "id": "user_xxx",
    "username": "testuser",
    "email": "test@example.com",
    "role": "annotator",
    "created_at": "2024-01-22T..."
  }
}

用户同步逻辑

首次登录

  1. OAuth 返回用户信息(包含 subid 字段)
  2. 系统检查本地数据库是否存在该 OAuth 用户
  3. 如果不存在,创建新用户记录:
    • oauth_provider: "sso"
    • oauth_id: OAuth 用户 ID
    • username: OAuth 用户名
    • email: OAuth 邮箱
    • role: "annotator"(默认)
    • password_hash: ""(OAuth 用户不需要密码)

再次登录

  1. 系统根据 oauth_provideroauth_id 查找用户
  2. 更新用户名和邮箱(如果有变化)
  3. 返回现有用户信息

角色管理

当前实现:

  • 所有 OAuth 用户默认角色为 annotator(标注员)
  • SSO 暂时未提供角色信息

未来扩展:

  • 当 SSO 提供角色信息后,可以从 OAuth 用户信息中读取角色
  • 支持 adminannotator 两种角色
  • 管理员可以删除项目和任务

安全特性

State 参数验证

  • 前端生成随机 state 参数并保存到 sessionStorage
  • OAuth 回调时验证 state 参数是否匹配
  • 防止 CSRF 攻击

Token 安全

  • OAuth access_token 仅用于获取用户信息
  • 系统生成独立的 JWT tokens 用于后续 API 调用
  • JWT tokens 有过期时间(access: 15分钟,refresh: 7天)

用户隔离

  • 每个 OAuth 用户在本地数据库有独立记录
  • 用户只能访问自己的标注数据
  • 管理员可以访问所有数据

故障排除

问题 1: "无效的客户端ID" 错误

原因: OAuth 服务器上的应用 ID 配置不正确

解决方案:

  • 确认 backend/config.yaml 中的 client_id 是正确的
  • 当前正确的 ID:sRyfcQwNVoFimigzuuZxhqd36fPkVN5G
  • 确认 OAuth 服务器上已创建该应用

问题 2: "无效的重定向URI" 错误

原因: 回调 URL 未在 OAuth 服务器上配置

解决方案:

  • 在 OAuth 服务器上添加回调 URL:http://localhost:4200/auth/callback
  • 确保 URL 完全匹配(包括协议、端口、路径)

问题 3: "授权码已被使用" 错误

原因: React StrictMode 在开发环境下会导致组件渲染两次,授权码被使用两次

解决方案:

  • 已在 oauth-callback.tsx 中添加防重复调用逻辑(使用 isProcessing 状态)
  • 生产环境不会有此问题(StrictMode 仅在开发环境启用)

问题 4: Client ID 和 Secret 配置错误

症状: 配置文件中 client_idclient_secret 的值搞反了

正确配置:

oauth:
  client_id: "sRyfcQwNVoFimigzuuZxhqd36fPkVN5G"
  client_secret: "96RuKb4obAn9bQ9i5NtINiKBMvF_9uuCR7eNzD9dWQMbOWZaV3P593-8yLOqzWRd"

问题 5: 点击"使用 SSO 登录"没有反应

检查:

  1. 打开浏览器控制台查看错误
  2. 确认后端 OAuth 配置正确
  3. 确认 OAuth 服务可访问

问题 6: 重定向到 OAuth 后无法返回

检查:

  1. 确认 redirect_uri 配置正确
  2. 确认 OAuth 中心配置了正确的回调 URL
  3. 检查浏览器控制台错误

问题 7: 回调后显示"登录失败"

检查:

  1. 查看浏览器控制台错误信息
  2. 查看后端日志
  3. 确认 OAuth 令牌交换成功
  4. 确认用户信息获取成功

问题 8: State 参数不匹配

原因: sessionStorage 被清除或浏览器不支持

解决方案:

  1. 不要在登录过程中清除浏览器缓存
  2. 确保浏览器支持 sessionStorage
  3. 检查是否有浏览器扩展干扰

测试账号

请使用 SSO 认证中心提供的测试账号进行测试。

开发调试

查看 OAuth 配置状态

curl http://localhost:8000/api/oauth/status

查看用户数据库

cd backend
sqlite3 annotation_platform.db
SELECT * FROM users WHERE oauth_provider = 'sso';

清除 OAuth 用户

cd backend
sqlite3 annotation_platform.db
DELETE FROM users WHERE oauth_provider = 'sso';

生产环境配置

更新回调 URL

修改 backend/config.yaml:

oauth:
  redirect_uri: "http://your-production-domain.com/auth/callback"

更新前端 CORS

修改 backend/main.py:

app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "http://your-production-domain.com",
    ],
    ...
)

总结

OAuth 单点登录已成功集成!主要特性:

  • ✅ 支持 OAuth 2.0 授权码模式
  • ✅ 自动用户同步和创建
  • ✅ State 参数防 CSRF 攻击
  • ✅ 独立的 JWT token 管理
  • ✅ 用户角色支持(默认 annotator)
  • ✅ 与现有认证系统兼容
  • ✅ 支持传统用户名密码登录

现在可以使用 SSO 登录标注平台了!🎉


实现日期: 2024-01-22
状态: ✅ 完成
文档版本: 1.0