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

实战篇:Python开发monogod数据库mcp server看完你就会了

实战篇:Python开发monogod数据库mcp server看完你就会了

原创不易,请关注公众号:【爬虫与大模型开发】,大模型的应用开发之路,整理了大模型在现在的企业级应用的实操及大家需要注意的一些AI开发的知识点!持续输出爬虫与大模型的相关文章。 前言 目前mcp协议是给deepseek大模型插上工具链的翅膀,让大模型不仅拥有超高的推理和文本生成能力,还能具备执行大脑意识的工具能力! 如何开发一个mcp? mcp是一种协议,指的是模型上下文协议 (Model Context Protocol)。 官方结成的mcp https://github.com/modelcontextprotocol/python-sdk mcp库 pip install mcp from mcp.server.fastmcp import FastMCP 我们先来做一个简单的案例 from mcp.server.fastmcp import FastMCP import requests mcp = FastMCP("spider") @mcp.tool() def crawl(

By Ne0inhk
【大模型实战篇】基于Claude MCP协议的智能体落地示例

【大模型实战篇】基于Claude MCP协议的智能体落地示例

1. 背景         之前我们在《MCP(Model Context Protocol) 大模型智能体第一个开源标准协议》一文中,介绍了MCP的概念,虽然了解了其概念、架构、解决的问题,但还缺少具体的示例,来帮助进一步理解整套MCP框架如何落地。         今天我们基于claude的官方例子--获取天气预报【1】,来理解MCP落地的整条链路。 2. MCP示例         该案例是构建一个简单的MCP天气预报服务器,并将其连接到主机,即Claude for Desktop。从基本设置开始,然后逐步发展到更复杂的使用场景。         大模型虽然能力非常强,但其弊端就是内容是过时的,这里的过时不是说内容很旧,只是表达内容具有非实时性。比如没有获取天气预报和严重天气警报的能力。因此我们将使用MCP来解决这一问题。         构建一个服务器,该服务器提供两个工具:获取警报(get-alerts)和获取预报(get-forecast)。然后,将该服务器连接到MCP主机(在本例中为Claude for Desktop)。         首先我们配置下环

By Ne0inhk
AI Agent新范式:FastGPT+MCP协议实现工具增强型智能体构建

AI Agent新范式:FastGPT+MCP协议实现工具增强型智能体构建

AI Agent新范式:FastGPT+MCP协议实现工具增强型智能体构建 作者:高瑞冬 本文目录 * AI Agent新范式:FastGPT+MCP协议实现工具增强型智能体构建 * 一、MCP协议简介 * 二、创建MCP工具集 * 1. 获取MCP服务地址 * 2. 在FastGPT中创建MCP工具集 * 三、测试MCP工具 * 四、AI模型调用MCP工具 * 1. 调用单个工具 * 2. 调用整个工具集 * 五、私有化部署支持 * 1. 环境准备 * 2. 修改docker-compose.yml文件 * 3. 修改FastGPT配置 * 4. 重启服务 * 六、使用MCP-Proxy集成多个MCP服务 * 1. MCP-Proxy简介 * 2. 安装MCP-Proxy * 3. 配置MCP-Proxy * 4. 将MCP-Proxy与FastGPT集成 * 5. 高级配置

By Ne0inhk
基于腾讯云HAI + DeepSeek快速设计自己的个人网页

基于腾讯云HAI + DeepSeek快速设计自己的个人网页

前言:通过结合腾讯云HAI 强大的云端运算能力与DeepSeek先进的 AI技术,本文介绍高效、便捷且低成本的设计一个自己的个人网页。你将了解到如何轻松绕过常见的技术阻碍,在腾讯云HAI平台上快速部署DeepSeek模型,仅需简单几步,就能获取一个包含个人简介、技能特长、项目经历及联系方式等核心板块的响应式网页。 目录 一、DeepSeek模型部署在腾讯云HAI 二、设计个人网页 一、DeepSeek模型部署在腾讯云HAI 把 DeepSeek 模型部署于腾讯云 HAI,用户便能避开官网访问限制,直接依托腾讯云 HAI 的超强算力运行 DeepSeek-R1 等模型。这一举措不仅降低了技术门槛,还缩短了部署时间,削减了成本。尤为关键的是,凭借 HAI 平台灵活且可扩展的特性,用户能够依据自身特定需求定制专属解决方案,进而更出色地适配特定业务场景,满足各类技术要求 。 点击访问腾讯云HAI控制台地址: 算力管理 - 高性能应用服务 - 控制台 腾讯云高性能应用服务HAI已支持DeepSeek-R1模型预装环境和CPU算力,只需简单的几步就能调用DeepSeek - R1

By Ne0inhk