# UniApp Google OAuth2.0 登录演示
> 🌐 纯前端实现谷歌第三方登录,支持 H5 与 App 双端,无需后端服务
📋 项目简介
本项目基于 UniApp 框架,实现了完整的 Google OAuth2.0 授权码模式登录流程,包含:
- ✅ 授权码模式(Authorization Code)纯前端实现
- ✅ H5 平台网页跳转授权
- ✅ App 平台深度链接回调(Android/iOS)
- ✅ CSRF 防护(state 参数校验)
- ✅ Token 缓存与自动刷新
- ✅ 国际化错误提示(中/英/西)
- ✅ 网络异常降级策略
🚀 快速开始
1. Google Cloud Console 配置
1.1 创建项目
- 访问 Google Cloud Console
- 点击顶部项目选择器 → "新建项目"
- 输入项目名称(如
MyApp-GoogleLogin) - 等待项目创建完成(约 30 秒)
1.2 配置 OAuth 同意屏幕
- 进入 "API 和服务" → "OAuth 同意屏幕"
- 用户类型选择 "外部"
- 填写必填项:
| 配置项 | 示例值 |
|---|---|
| 应用名称 | MyAwesomeApp |
| 用户支持邮箱 | |
| 开发者联系信息 | |
| 授权域名 | myapp.com |
- 测试用户:添加所有需要测试的 Google 账号(否则提示"未经验证的应用")
1.3 创建 OAuth 客户端凭据
- 进入 "凭据" 页面 → "创建凭据" → "OAuth 客户端 ID"
- 应用类型选择 "Web 应用"
- 配置授权 JavaScript 来源和重定向 URI:
开发环境配置:
{ "authorizedJavaScriptOrigins": [ "http://localhost:8080", "http://localhost:9000" ], "authorizedRedirectUris": [ "http://localhost:8080/callback", "http://localhost:9000/callback", "com.myapp://callback" ] }
生产环境配置:
{ "authorizedJavaScriptOrigins": [ "https://yourdomain.com" ], "authorizedRedirectUris": [ "https://yourdomain.com/callback", "com.myapp://callback" ] }
- 复制生成的 客户端 ID(格式:
xxx.apps.googleusercontent.com)
2. 项目配置
2.1 修改 Client ID
打开 common/config.js,替换为你的客户端 ID:
export const GOOGLE_CLIENT_ID = 'YOUR_CLIENT_ID.apps.googleusercontent.com';
2.2 HBuilderX 运行配置
- 使用 HBuilderX 打开项目
- 运行到浏览器(H5):
- 菜单栏 → 运行 → 运行到浏览器 → Chrome
- 默认端口:8080
- 访问地址:
http://localhost:8080
- 运行到真机(App):
- 连接 Android/iOS 设备
- 菜单栏 → 运行 → 运行到手机或模拟器
3. 多平台适配
H5 平台
- 回调地址:
http://localhost:8080/callback - 确保 Google 控制台配置的 授权 JavaScript 来源 包含当前访问域名
- 生产环境必须使用 HTTPS
Android 平台
在 manifest.json 中已配置 Intent Filter:
"app-plus": { "distribute": { "android": { "intentFilters": [ { "action": ["android.intent.action.VIEW"], "category": ["android.intent.category.DEFAULT", "android.intent.category.BROWSABLE"], "data": { "scheme": "com.myapp" } } ] } } }
如需自定义 scheme,请修改为包名(如 com.yourcompany.yourapp)。
iOS 平台
在 manifest.json 中已配置 URL Types:
"app-plus": { "distribute": { "ios": { "urlTypes": [ { "urlScheme": "com.myapp", "urls": ["com.myapp://callback"] } ] } } }
Universal Links(可选高级配置):
- 创建
apple-app-site-association文件并部署到服务器 - 在 Xcode 中配置 Associated Domains 能力
- 在 Google 控制台添加 Universal Link 作为回调 URI
🔒 安全**实践
1. CSRF 防护
项目已实现 state 参数生成与校验:
// 生成随机 state const state = generateState(); uni.setStorageSync('oauth_state', state); // 回调时校验 const savedState = uni.getStorageSync('oauth_state'); if (state !== savedState) { throw new Error('Invalid state parameter'); }
2. Token 存储
- 使用
uni.setStorageSync加密存储 - 避免长期存储 access_token
- 添加客户端过期检查
3. HTTPS 强制
生产环境必须启用 HTTPS:
- 避免中间人攻击
- 所有回调地址必须为 HTTPS
- Google OAuth 要求生产环境使用 HTTPS
🛠️ 常见问题排查
错误代码速查表
| 错误代码 | 可能原因 | 解决方案 |
|---|---|---|
400 invalid_request |
参数缺失或格式错误 | 检查 redirect_uri 编码 |
403 access_denied |
用户取消授权 | 优化 UI 引导文案 |
redirect_uri_mismatch |
回调地址不匹配 | 检查 Google 控制台配置 |
invalid_grant |
code 过期或已使用 | 重新发起授权 |
H5 调试技巧
- 开启调试模式:在 URL 中添加
?debug=oauth - 拦截网络请求:
const originalFetch = window.fetch; window.fetch = async function(...args) { console.log('Fetch:', args); const response = await originalFetch(...args); console.log('Response:', await response.clone().json()); return response; };
真机调试
Android 日志:
adb logcat | grep 'OAuth'
iOS 控制台:
- 打开 Safari → 开发 → 选择设备 → 搜索 "oauth"
📊 性能优化
1. 预加载授权页面
onLaunch() }
2. Token 缓存
async function getTokenWithCache(code) { const cacheKey = `token_${code.substr(0, 8)}`; const cached = uni.getStorageSync(cacheKey); if (cached) return cached; const token = await exchangeToken(code); uni.setStorageSync(cacheKey, token, 60 * 60 * 1000); // 缓存 1 小时 return token; }
3. 按需加载 Google SDK
function loadGoogleSDK() ); }
🌍 国际化支持
项目支持中文、英文、西班牙文三种语言:
const ERROR_MAP = { 'invalid_request': { en: 'Invalid request', zh: '请求参数错误', es: 'Solicitud no válida' }, // ...其他错误码 };
语言自动根据系统设置切换,也可手动调用 setLanguage('en')。
🔄 降级策略
当 Google 服务不可用时,自动切换到邮箱密码登录:
📈 进阶:前后端分离方案
虽然本项目是纯前端实现,但生产环境推荐采用前后端分离的安全架构:
混合模式流程
- 前端获取授权码(code)
- 将 code 发送到自家后端
- 后端用 code + client_secret 交换令牌
- 后端返回自定义认证 token
优势对比
| 方案 | 安全性 | 复杂度 | 用户体验 |
|---|---|---|---|
| 纯前端 | 低 | 简单 | 流畅 |
| 前后端分离 | 高 | 中等 | 需额外跳转 |
| 服务端渲染 | 最高 | 复杂 | 较差 |
📝 项目结构
”` ├── App.vue # 应用入口 ├── main.js # 入口 JS ├── manifest.json # 应用配置 ├── pages.json
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/267841.html