# 认证集成说明 ## 概述 本应用已实现与网页端(https://cstb.upup.cool/)的邮箱注册登录功能集成。用户可以通过网页端登录/注册,然后通过 deep-link 回调到本地应用。 ## 实现方案 ### 1. 用户流程 1. 用户在本地应用中点击"登录"或"注册"按钮 2. 应用打开浏览器,跳转到网页端登录/注册页面 3. 用户在网页端完成登录/注册 4. 网页端重定向到 `cstb://auth` deep-link,携带认证信息 5. 本地应用接收 deep-link 回调,解析并设置 session 6. 用户状态同步到本地应用 ### 2. 技术实现 #### 前端(Next.js + Tauri) - **认证 Store** (`src/store/auth.ts`): 管理用户状态和会话 - **认证工具** (`src/utils/auth.ts`): 处理登录/注册跳转和回调解析 - **认证 Provider** (`src/components/auth/AuthProvider.tsx`): 监听 deep-link 和认证状态变化 - **认证按钮** (`src/components/auth/AuthButton.tsx`): UI 组件,显示登录状态和用户信息 #### Deep-link 配置 - Scheme: `cstb` - 回调 URL 格式: `cstb://auth?access_token=xxx&refresh_token=xxx` 或 `cstb://auth?code=xxx` ### 3. 网页端集成要求 网页端需要在登录/注册成功后,重定向到 deep-link URL。以下是几种实现方式: #### 方式 1: 使用 access_token 和 refresh_token(推荐) ```typescript // 在登录成功后 const { data } = await supabase.auth.signInWithPassword({ email, password }) if (data.session) { const redirectUrl = new URL('cstb://auth', window.location.href) redirectUrl.searchParams.set('access_token', data.session.access_token) redirectUrl.searchParams.set('refresh_token', data.session.refresh_token) window.location.href = redirectUrl.toString() } ``` #### 方式 2: 使用 PKCE flow(更安全) ```typescript // 在登录页面初始化时 const { data } = await supabase.auth.signInWithOAuth({ provider: 'email', options: { redirectTo: 'cstb://auth' } }) // 处理回调 const { data: { session } } = await supabase.auth.getSession() if (session) { window.location.href = 'cstb://auth?code=' + session.access_token } ``` #### 方式 3: 使用完整 session JSON ```typescript // 在登录成功后 const { data } = await supabase.auth.signInWithPassword({ email, password }) if (data.session) { const redirectUrl = new URL('cstb://auth', window.location.href) redirectUrl.searchParams.set('session', encodeURIComponent(JSON.stringify(data.session))) window.location.href = redirectUrl.toString() } ``` ### 4. 网页端修改示例 在 `https://cstb.upup.cool/auth/login` 和 `https://cstb.upup.cool/auth/signup` 页面中: ```typescript // 检查是否有 redirect 参数 const urlParams = new URLSearchParams(window.location.search) const redirectTo = urlParams.get('redirect') // 应该是 'cstb://auth' // 登录成功后 const handleLogin = async (email: string, password: string) => { const { data, error } = await supabase.auth.signInWithPassword({ email, password, }) if (error) { // 处理错误 return } if (data.session && redirectTo) { // 重定向到 deep-link const redirectUrl = new URL(redirectTo) redirectUrl.searchParams.set('access_token', data.session.access_token) redirectUrl.searchParams.set('refresh_token', data.session.refresh_token) window.location.href = redirectUrl.toString() } else { // 正常网页端跳转 window.location.href = '/' } } ``` ### 5. 环境变量 确保以下环境变量已配置: ```env NEXT_PUBLIC_SUPABASE_URL=your_supabase_url NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key ``` ### 6. 测试 1. 启动应用 2. 点击导航栏的用户图标 3. 选择"登录"或"注册" 4. 在浏览器中完成登录/注册 5. 应用应该自动接收回调并显示登录成功提示 ## 注意事项 1. **安全性**: 虽然 access_token 和 refresh_token 通过 URL 传递,但由于 deep-link 是本地协议,相对安全。但建议使用 PKCE flow 以获得更好的安全性。 2. **错误处理**: 网页端应该处理登录失败的情况,不要重定向到 deep-link。 3. **用户体验**: 可以在网页端显示"正在跳转到应用..."的提示,提升用户体验。 4. **兼容性**: 确保 deep-link 在所有目标平台上都已正确注册(Windows/macOS/Linux)。 ## 故障排查 1. **Deep-link 未触发**: 检查 `tauri.conf.json` 中 deep-link 配置是否正确 2. **Session 未保存**: 检查 Supabase client 配置,确保使用 localStorage 3. **回调参数错误**: 检查网页端传递的参数格式是否正确