Flutter for OpenHarmony:oauth2 标准化实现第三方登录与 Token 管理(OAuth2.0 认证客户端) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:oauth2 标准化实现第三方登录与 Token 管理(OAuth2.0 认证客户端) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net

前言

在现代 App 开发中,对接第三方认证(如 Google、GitHub 登录)是不可或缺的功能。OAuth 2.0 协议虽然标准,但由于涉及复杂的认证流、Token 刷新和存储,手动实现极易出错。

Dart 官方提供的 oauth2 库封装了完整的客户端认证逻辑,支持多种授权模式,并能自动处理 Access Token 的过期刷新。本文将演示如何在 OpenHarmony 应用中优雅地集成 oauth2,实现安全的身份认证。

一、oauth2 简介

1.1 核心功能

  • 多种授权模式:支持 Authorization Code, Client Credentials, Resource Owner Password 等。
  • 自动刷新:一旦 Token 过期,自动使用 Refresh Token 获取新凭证。
  • 持久化:方便地序列化和反序列化 Credentials 对象,以便存储。

1.2 OpenHarmony 适配说明

oauth2 是纯 Dart 实现,通过 http 包进行网络通信。因此在 OpenHarmony 上运行时,只需确保网络权限配置正确即可。

认证服务器 (GitHub/Google)系统浏览器OpenHarmony 应用用户认证服务器 (GitHub/Google)系统浏览器OpenHarmony 应用用户点击登录打开授权 URL用户确认授权重定向并携带 ?code=...通过 Deep Link 回调应用使用 code 交换访问令牌 (Token)返回 Access & Refresh Token持久化保存凭证

二、配置与准备

2.1 添加依赖

dependencies:oauth2: ^2.0.5 url_launcher: ^6.3.0 # 用于打开系统浏览器进行用户授权http: ^1.2.0 dependency_overrides:url_launcher_ohos:git:url: https://atomgit.com/openharmony-sig/flutter_packages.git path: packages/url_launcher/url_launcher_ohos 

2.2 网络权限

module.json5 中添加网络权限:

"requestPermissions":[{"name":"ohos.permission.INTERNET"}]

三、核心授权模式与示例

3.1 示例一:客户端凭据模式 (Client Credentials)

适用于服务器对服务器的通信,不涉及用户交互。

import'package:oauth2/oauth2.dart'as oauth2;Future<void>clientCredentialsGrant()async{final authorizationEndpoint =Uri.parse("https://example.com/oauth2/token");final identifier ="my_client_id";final secret ="my_client_secret";// 创建客户端var client =await oauth2.clientCredentialsGrant( authorizationEndpoint, identifier, secret,);// 使用 client 发起请求,它会自动带上 Bearer Tokenvar response =await client.read(Uri.parse("https://example.com/api/resource"));print("资源内容: $response");// 记得关闭 client.close();}
在这里插入图片描述

3.2 示例二:资源所有者密码模式 (Resource Owner Password)

用户直接向客户端提供用户名和密码(仅在高度信任的应用中使用)。

import'package:oauth2/oauth2.dart'as oauth2;Future<void>passwordGrant(String username,String password)async{final endpoint =Uri.parse("https://example.com/oauth2/token");try{var client =await oauth2.resourceOwnerPasswordGrant( endpoint, username, password, identifier:"my_client_id", secret:"my_client_secret",);print("登录成功,AccessToken: ${client.credentials.accessToken}");}catch(e){print("认证失败: $e");}}
在这里插入图片描述

3.3 示例三:凭证存储与恢复

为了避免用户每次打开 App 都要重新登录,我们需要存储 Credentials。

import'dart:convert';import'package:oauth2/oauth2.dart'as oauth2;// 假设使用 shared_preferences// import 'package:shared_preferences/shared_preferences.dart';Future<void>saveCredentials(oauth2.Client client)async{// 序列化String json = client.credentials.toJson();print("保存凭证: $json");// await prefs.setString('oauth_credentials', json);}Future<oauth2.Client?>loadCredentials()async{// String? json = prefs.getString('oauth_credentials');String? json ='{"accessToken": "..."}';// 模拟读取if(json !=null){var credentials =oauth2.Credentials.fromJson(json);returnoauth2.Client(credentials, identifier:"client_id", secret:"client_secret");}returnnull;}
在这里插入图片描述

四、完整实战示例:GitHub 授权登录

本示例演示最常用的 Authorization Code Grant 模式。用户点击登录 -> 跳转浏览器授权 -> 回调 App -> 获取 Token。

4.1 准备工作

OpenHarmony 需要处理 Deep Link (App Link) 才能从浏览器跳回应用,这部分配置较为复杂。为简化示例,我们将模拟重定向后的 URL 输入,或者在实际设备上配置 skills 里的 uris

这里展示核心逻辑代码。

4.2 示例代码

import'package:flutter/material.dart';import'package:oauth2/oauth2.dart'as oauth2;import'package:url_launcher/url_launcher.dart';import'package:http/http.dart'as http;final _authorizationEndpoint =Uri.parse('https://github.com/login/oauth/authorize');final _tokenEndpoint =Uri.parse('https://github.com/login/oauth/access_token');final _identifier ='YOUR_GITHUB_CLIENT_ID';final _secret ='YOUR_GITHUB_CLIENT_SECRET';final _redirectUrl =Uri.parse('my.app://oauth-callback');voidmain(){runApp(constMaterialApp(home:OAuthLoginPage()));}classOAuthLoginPageextendsStatefulWidget{constOAuthLoginPage({super.key});@overrideState<OAuthLoginPage>createState()=>_OAuthLoginPageState();}class _OAuthLoginPageState extendsState<OAuthLoginPage>{oauth2.Client? _client;oauth2.AuthorizationCodeGrant? _grant;Future<void>_login()async{// 1. 创建授权请求管理对象 _grant =oauth2.AuthorizationCodeGrant( _identifier, _authorizationEndpoint, _tokenEndpoint, secret: _secret, httpClient:_JsonAcceptingHttpClient(),// GitHub 需要 Accept: application/json);// 2. 获取授权 URLvar authorizationUrl = _grant!.getAuthorizationUrl(_redirectUrl, scopes:['read:user']);// 3. 打开浏览器 (OpenHarmony 上 url_launcher 可正常工作)if(awaitcanLaunchUrl(authorizationUrl)){awaitlaunchUrl(authorizationUrl, mode:LaunchMode.externalApplication);}// ⚠️ 注意:真实场景中,App 需要配置 Deep Link 监听// 当浏览器跳转回 my.app://oauth-callback?code=... 时,捕获该 URL// 这里为了演示,我们模拟手动输入回调 URL_showManualInputCallback();}void_handleCallback(Uri responseUrl)async{try{// 4. 交换 Tokenvar client =await _grant!.handleAuthorizationResponse(responseUrl.queryParameters);setState((){ _client = client;});_getUserInfo();}catch(e){print("授权失败: $e");}}Future<void>_getUserInfo()async{if(_client ==null)return;try{var response =await _client!.read(Uri.parse('https://api.github.com/user'));print("用户信息: $response");// 显示用户信息...}catch(e){print("获取信息失败: $e");}}void_showManualInputCallback(){showDialog( context: context, builder:(ctx){final controller =TextEditingController();returnAlertDialog( title:constText("模拟回调"), content:Column( mainAxisSize:MainAxisSize.min, children:[constText("在真实 App 中,这一步由 Deep Links 自动完成。现在请手动粘贴浏览器地址栏的回调 URL:"),TextField(controller: controller, decoration:constInputDecoration(hintText:"my.app://...?code=...")),],), actions:[TextButton( onPressed:(){Navigator.pop(ctx);if(controller.text.isNotEmpty){_handleCallback(Uri.parse(controller.text));}}, child:constText("确定"))],);});}@overrideWidgetbuild(BuildContext context){returnScaffold( appBar:AppBar(title:constText('OAuth2 GitHub 登录')), body:Center( child: _client ==null?ElevatedButton( onPressed: _login, child:constText('Login with GitHub'),):Column( mainAxisAlignment:MainAxisAlignment.center, children:[constText("登录成功!"),constSizedBox(height:20),constText("AccessToken 已获取"),ElevatedButton( onPressed: _getUserInfo, child:constText("刷新用户信息")),],),),);}}// 辅助类:GitHub API 默认返回 XML 格式 Token,需强制要求 JSONclass _JsonAcceptingHttpClient extendshttp.BaseClient{final _httpClient =http.Client();@overrideFuture<http.StreamedResponse>send(http.BaseRequest request){ request.headers['Accept']='application/json';return _httpClient.send(request);}}
在这里插入图片描述

五、总结

oauth2 库极大简化了在 OpenHarmony 上实现标准认证流程的工作。结合 url_launcher 和 deep links,可以构建流畅的第三方登录体验。

最佳实践

  1. 安全存储:不要将 client_secret 硬编码在代码中,建议通过混淆或服务端代理获取。
  2. 凭证管理:务必持久化保存 Credentials,并在 App 启动时尝试恢复,避免用户重复登录。
  3. OpenHarmony Deep Link:深入研究 module.json5 中的 uris 配置,确保浏览器能正确唤起 App。

Read more

【AI辅助编程】【Claude Code】----秒杀 Cursor!Claude Code 保姆级教程,从安装到实战全过程,一篇文章给你透

【AI辅助编程】【Claude Code】----秒杀 Cursor!Claude Code 保姆级教程,从安装到实战全过程,一篇文章给你透

文章目录 * 前言 * 一、基础概念解析, * 1.1、什么是Claude Code? * 1.2、Claude Code能干嘛? * 二、安装 Claude Code * 2.1、(方式一)基于node.js环境 * 2.2、(方式二)不依赖node.js环境,原生版(推荐) * 三、配置 * 3.1配置大模型端点和密钥 * 1.注册账号 (通过上面提供的连接注册) * 2.获取API Key * 3.配置cluade code 环境变量 * 4.测试配置: * 5.切换模型(非必要,可跳过) * 6.查看token用量

By Ne0inhk
AskGo:免费使用顶级AI的宝藏网站(Gemini 3、GPT 5.1、DeepSeek)

AskGo:免费使用顶级AI的宝藏网站(Gemini 3、GPT 5.1、DeepSeek)

这几年,AI大模型可谓是极速迭代,在激烈的竞争下,国内的AI大模型能力也有了质的飞跃,如通义千问、豆包、GLM、Kimi等。 但其实国外的AI大模型目前依然呈领先趋势,只是很多人在国内无法使用。 那么今天给大家推荐一个能够同时使用国内外顶级AI的网站——AskGo! AskGo集成了ChatGPT、DeepSeek、Gemini、Claude、Grok等数十个顶尖大模型,覆盖聊天、搜索、深度阅读、创意写作、程序开发、专业翻译、图像生成及视频生成等全场景。无需再做选择题,你可以随时利用最前沿的AI技术解决复杂问题。 AskGo为您提供「一站式AI」综合解决方案: ✅ 国内直接使用数十款顶级AI。包含GPT 5.1、Gemini 3 pro、Claude 4.5、Grok 4.1、DeepSeek满血版、Nano Banana Pro、GPT-4o绘图、Sora2、Veo3.1等顶级模型。

By Ne0inhk

AI 编程工具终极对决:Trae 3.0, Cursor, Qoder, Claude Code, Gemini 全方位评测

AI 编程工具终极对决:Trae 3.0, Cursor, Qoder, Claude Code, Gemini 全方位评测 更新时间:2025年12月 2025 年是 AI 编程工具进化的分水岭。如果说 GitHub Copilot 开启了 “AI 补全” 的 1.0 时代,Cursor 定义了 “AI Native IDE” 的 2.0 时代,那么随着 Trae 3.0、Qoder 的成熟,我们正式进入了 Agentic Coding(代理式编程) 的 3.0 时代。

By Ne0inhk