Flutter 开发的鸿蒙AtomGit OAuth 授权应用
项目概述
这是一个基于 Flutter 开发的鸿蒙OAuth 2.0 授权应用,用于获取 AtomGit 授权用户的个人信息。应用实现了完整的 OAuth 授权流程,包括:
- ✅ OAuth 2.0 授权码模式
- ✅ 访问令牌获取和刷新
- ✅ 用户信息获取和展示
- ✅ 令牌本地存储和管理
- ✅ 自动令牌刷新机制

功能特性
1. OAuth 授权流程
- 使用 WebView 进行 OAuth 授权
- 自动捕获授权回调
- 获取访问令牌和刷新令牌
2. 用户信息展示
- 用户基本信息(头像、姓名、用户名等)
- 统计信息(关注者、关注中)
- 常用编程语言
- 个人主页链接
3. 令牌管理
- 本地存储访问令牌和刷新令牌
- 自动检测令牌过期
- 自动刷新过期令牌
- 退出登录功能
配置步骤
步骤 1:创建 OAuth 应用
-
登录 AtomGit
-
进入 设置 → 应用 → 开发者设置
-
点击 新建应用
-
填写应用信息:
- 应用名称:你的应用名称
- 应用描述:应用描述
- 应用主页:你的应用主页 URL
- 回调地址 :你的重定向 URI(例如:
myapp://oauth/callback) - 权限范围 :选择需要的权限(例如:
read:user,user:email)
-
创建完成后,记录以下信息:
- Client ID
- Client Secret
步骤 2:配置应用
打开 lib/services/oauth_service.dart 文件,修改以下配置:
dart
// 这些值需要从你的 OAuth 应用配置中获取
static const String clientId = 'YOUR_CLIENT_ID'; // 替换为你的 Client ID
static const String clientSecret = 'YOUR_CLIENT_SECRET'; // 替换为你的 Client Secret
static const String redirectUri = 'YOUR_REDIRECT_URI'; // 替换为你的重定向 URI
示例:
dart
static const String clientId = 'abc123def456';
static const String clientSecret = 'secret_key_here';
static const String redirectUri = 'myapp://oauth/callback';
步骤 3:配置重定向 URI(Android)
如果使用 Android 平台,需要在 android/app/src/main/AndroidManifest.xml 中添加 Intent Filter:
xml
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme">
<!-- 其他配置 -->
<!-- 添加 OAuth 回调 Intent Filter -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="myapp"
android:host="oauth"
android:pathPrefix="/callback" />
</intent-filter>
</activity>
注意 :android:scheme 和 android:host 需要与你的 redirectUri 匹配。
步骤 4:配置重定向 URI(iOS)
如果使用 iOS 平台,需要在 ios/Runner/Info.plist 中添加 URL Scheme:
xml
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
项目结构
lib/
├── main.dart # 应用入口,授权检查页面
├── services/
│ ├── oauth_service.dart # OAuth API 服务
│ └── storage_service.dart # 本地存储服务
└── pages/
├── oauth_page.dart # OAuth 授权页面
└── user_info_page.dart # 用户信息展示页面
核心功能说明
1. OAuth 授权流程
dart
// 获取授权 URL
String authUrl = OAuthService.getAuthorizationUrl();
// 在 WebView 中打开授权页面
// 用户授权后,会重定向到 redirectUri,并携带授权码
// 使用授权码获取访问令牌
OAuthToken token = await OAuthService.getAccessToken(code);
2. 获取用户信息
dart
// 使用访问令牌获取用户信息
UserInfo userInfo = await OAuthService.getUserInfo(accessToken);
3. 刷新令牌
dart
// 当访问令牌过期时,使用刷新令牌获取新的访问令牌
OAuthToken newToken = await OAuthService.refreshAccessToken(refreshToken);
4. 本地存储
dart
// 保存访问令牌
await StorageService.saveAccessToken(token);
// 获取访问令牌
String? token = await StorageService.getAccessToken();
// 检查令牌是否过期
bool isExpired = await StorageService.isTokenExpired();
// 清除所有令牌
await StorageService.clearTokens();
API 接口说明
1. 获取访问令牌
接口: POST https://gitcode.com/oauth/token
请求参数:
grant_type:authorization_code(获取新 token)或refresh_token(刷新 token)code: 授权码(获取新 token 时必填)client_id: 客户端 ID(获取新 token 时必填)client_secret: 客户端密钥(获取新 token 时在 Body 中传递)refresh_token: 刷新令牌(刷新 token 时必填)
响应示例:
json
{
"access_token": "your_access_token",
"expires_in": 7200,
"refresh_token": "your_refresh_token",
"scope": "read:user",
"created_at": "2024-01-01T00:00:00Z"
}
2. 获取用户信息
接口: GET https://api.gitcode.com/api/v5/user
请求参数:
access_token: 访问令牌(Query 参数)
响应示例:
json
{
"id": "123456",
"login": "username",
"name": "User Name",
"email": "user@example.com",
"avatar_url": "https://gitcode.com/avatars/123456",
"bio": "User bio",
"blog": "https://blog.example.com",
"company": "Company Name",
"html_url": "https://gitcode.com/username",
"followers": 100,
"following": 50,
"top_languages": ["Dart", "JavaScript", "Python"]
}
使用流程
-
启动应用
- 应用会自动检查是否有有效的访问令牌
- 如果有,直接跳转到用户信息页面
- 如果没有,跳转到 OAuth 授权页面
-
OAuth 授权
- 在 WebView 中打开 GitCode 授权页面
- 用户登录并授权
- 授权成功后,应用自动获取访问令牌
-
查看用户信息
- 自动获取并展示用户信息
- 支持下拉刷新
- 支持退出登录
-
令牌管理
- 应用会自动检测令牌是否过期
- 如果过期,会自动尝试刷新令牌
- 如果刷新失败,会提示重新授权
注意事项
1. 安全性
- ⚠️ 不要将 Client Secret 提交到代码仓库
- ⚠️ 建议使用环境变量或配置文件管理敏感信息
- ⚠️ 在生产环境中,考虑将 Client Secret 存储在服务器端
2. 重定向 URI
- 重定向 URI 必须与 OAuth 应用中配置的完全一致
- 支持自定义 URL Scheme(如:
myapp://oauth/callback) - 也支持 HTTP/HTTPS URL(需要配置相应的域名)
3. 令牌管理
- 访问令牌通常有有效期(如:7200 秒)
- 刷新令牌的有效期通常更长
- 建议在令牌过期前主动刷新
4. 错误处理
- 网络错误:检查网络连接
- 授权失败:检查 Client ID 和 Client Secret
- 令牌过期:应用会自动尝试刷新,失败后提示重新授权
常见问题
Q1: 授权后无法获取令牌?
A: 检查以下几点:
- Client ID 和 Client Secret 是否正确
- 重定向 URI 是否与 OAuth 应用配置一致
- 授权码是否有效(授权码只能使用一次)
Q2: 无法获取用户信息?
A: 检查以下几点:
- 访问令牌是否有效
- 访问令牌是否过期
- 是否有相应的权限范围(scope)
Q3: WebView 无法打开授权页面?
A: 检查以下几点:
- 网络连接是否正常
- 授权 URL 是否正确
- 是否需要在 AndroidManifest.xml 中添加网络权限
Q4: 令牌刷新失败?
A: 检查以下几点:
- 刷新令牌是否有效
- 刷新令牌是否过期
- 如果刷新失败,需要重新授权
扩展功能
1. 添加更多用户信息
可以在 UserInfo 模型中添加更多字段,并在 getUserInfo 方法中解析。
2. 添加其他 API 调用
参考 OAuthService 的实现,可以添加其他 GitCode API 的调用方法。
3. 改进 UI
可以根据需要自定义用户信息页面的 UI 设计。
4. 添加错误重试机制
可以实现更完善的错误处理和重试逻辑。
技术栈
- Flutter: 跨平台 UI 框架
- http: HTTP 请求库
- webview_flutter: WebView 组件
- shared_preferences: 本地存储
- url_launcher: URL 启动器(可选)
参考资料
注意:这是一个示例应用,用于演示 OAuth 2.0 授权流程。在生产环境中使用时,请确保遵循安全最佳实践。