跳到主要内容

如何使用 Flutter 构建 Discord 登录

· 阅读需 1 分钟
Logto team
The better identity infrastructure for developers
给我们的新朋友:

Logto 是一个为现代应用和 SaaS 产品设计的 Auth0 替代方案。它提供 Cloud开源 服务,帮助你快速启动身份和管理 (IAM) 系统。享受认证 (Authentication)、授权 (Authorization) 和多租户管理 一体化

我们建议从 Logto Cloud 上的免费开发租户开始。这可以让你轻松探索所有功能。

在本文中,我们将介绍使用 FlutterLogto 快速构建 Discord 登录体验(用户认证 (Authentication))的步骤。

先决条件

  • 一个正在运行的 Logto 实例。查看 介绍页面 以开始。
  • Flutter 的基本知识。
  • 一个可用的 Discord 账户。

在 Logto 中创建一个应用程序

Logto 基于 OpenID Connect (OIDC) 认证 (Authentication) 和 OAuth 2.0 授权 (Authorization)。它支持跨多个应用程序的联合身份管理,通常称为单点登录 (SSO)。

要创建你的 Native app 应用程序,只需按照以下步骤操作:

  1. 打开 Logto Console。在“开始使用”部分,点击“查看全部”链接以打开应用程序框架列表。或者,你可以导航到 Logto Console > Applications,然后点击“创建应用程序”按钮。 开始使用
  2. 在打开的模态窗口中,点击“Native app”部分,或使用左侧的快速过滤复选框过滤所有可用的“Native app”框架。点击 "Flutter" 框架卡片以开始创建你的应用程序。 框架
  3. 输入应用程序名称,例如“Bookstore”,然后点击“创建应用程序”。

🎉 太棒了!你刚刚在 Logto 中创建了你的第一个应用程序。你将看到一个祝贺页面,其中包含详细的集成指南。按照指南查看你的应用程序中的体验将会是什么样的。

集成 Flutter SDK

提示:
  • SDK 包可以在 pub.dev 和 Logto GitHub 仓库 上获取。
  • 示例项目是使用 Flutter material 构建的。你可以在 pub.dev 和我们的 GitHub 仓库 上找到它。
  • SDK 仅兼容 Android 和 iOS 平台。
  • SDK v1.x 兼容 Dart 2.x。对于 SDK v2.x,你需要将 Dart 版本更新到 3.x 或更高。

安装

你可以使用 pub 包管理器直接安装 logto_dart_sdk package。在你的项目根目录下运行以下命令:

flutter pub get logto_dart_sdk

模块

logto_dart_sdk 包含两个主要模块:

  • logto_core.dart 这个核心模块提供了 Logto SDK 的基本功能和接口。

  • logto_client.dart 这个客户端模块提供了一个高级的 Logto 客户端类,用于与 Logto 服务器交互。

依赖和配置

依赖和配置

此 SDK 具有以下依赖项,其中一些需要额外配置:

flutter_secure_storage

我们使用 flutter_secure_storage 来实现跨平台的持久安全令牌存储。

  • iOS 使用 Keychain
  • Android 使用 AES 加密。

配置 Android 版本

在项目的 android/app/build.gradle 文件中将 android:minSdkVersion 设置为 18。

build.gradle
  android {
...

defaultConfig {
...
minSdkVersion 18
...
}
}

禁用自动备份

默认情况下,Android 可能会自动在 Google Drive 上备份数据。这可能导致异常 java.security.InvalidKeyException:Failed to unwrap key

为避免这种情况,你可以禁用应用的自动备份或从 FlutterSecureStorage 中排除 sharedprefs

  1. 要禁用自动备份,请转到应用的清单文件,并将 android:allowBackupandroid:fullBackupContent 属性设置为 false

    AndroidManifest.xml
    <manifest ... >
    ...
    <application
    android:allowBackup="false"
    android:fullBackupContent="false"
    ...
    >
    ...
    </application>
    </manifest>

  2. FlutterSecureStorage 中排除 sharedprefs

    如果你需要保留应用的 android:fullBackupContent 而不是禁用它,可以从备份中排除 sharedprefs 目录。 请参阅 Android 文档 了解更多详情。

    在 AndroidManifest.xml 文件中,将 android:fullBackupContent 属性添加到 <application> 元素,如以下示例所示。此属性指向一个包含备份规则的 XML 文件。

    AndroidManifest.xml
    <application ...
    android:fullBackupContent="@xml/backup_rules">
    </application>

    res/xml/ 目录中创建一个名为 @xml/backup_rules 的 XML 文件。在此文件中,使用 <include><exclude> 元素添加规则。以下示例备份所有共享首选项,除了 device.xml:

    @xml/backup_rules
    <?xml version="1.0" encoding="utf-8"?>
    <full-backup-content>
    <exclude domain="sharedpref" path="FlutterSecureStorage"/>
    </full-backup-content>

请查看 flutter_secure_storage 了解更多详情。

flutter_web_auth

flutter_web_auth 在 Logto 的 flutter SDK 背后使用。我们依赖其基于 webview 的交互界面来认证用户。

备注:

此插件在 iOS 12+ 和 macOS 10.15+ 上使用 ASWebAuthenticationSession,在 iOS 11 上使用 SFAuthenticationSession,在 Android 上使用 Chrome Custom Tabs,并在 Web 上打开一个新窗口。

在 Android 上注册回调 url

为了捕获 Logto 登录网页的回调 url,你需要将登录的 redirectUri 注册到 AndroidManifest.xml 文件中。

AndroidManifest.xml
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" android:exported="true">
<intent-filter android:label="flutter_web_auth">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="io.logto"/>
</intent-filter>
</activity>

http.dart

由于 SDK 需要进行网络请求,你需要向 SDK 传入一个 HTTP 客户端。你可以使用来自 http.dart 的默认 http.Client,或者创建一个具有自定义配置的 http.Client


import 'package:http/http.dart' as http;

集成

初始化 LogtoClient

导入 logto_dart_sdk 包,并在应用程序的根部初始化 LogtoClient 实例。

lib/main.dart
import 'package:logto_dart_sdk/logto_dart_sdk.dart';
import 'package:http/http.dart' as http;

void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);


Widget build(BuildContext context) {
return const MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(title: 'Logto Demo Home Page'),
);
}
}

class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;


State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
late LogtoClient logtoClient;

void render() {
// 状态变化
}

// LogtoConfig
final logtoConfig = const LogtoConfig(
endpoint: "<your-logto-endpoint>",
appId: "<your-app-id>"
);

void _init() {
logtoClient = LogtoClient(
config: logtoConfig,
httpClient: http.Client(), // 可选的 http 客户端
);
render();
}


void initState() {
super.initState();
_init();
}

// ...
}

实现登录

在我们深入细节之前,这里是终端用户体验的快速概述。登录过程可以简化如下:

  1. 你的应用调用登录方法。
  2. 用户被重定向到 Logto 登录页面。对于原生应用,将打开系统浏览器。
  3. 用户登录并被重定向回你的应用(配置为重定向 URI)。

关于基于重定向的登录

  1. 此认证 (Authentication) 过程遵循 OpenID Connect (OIDC) 协议,Logto 强制执行严格的安全措施以保护用户登录。
  2. 如果你有多个应用程序,可以使用相同的身份提供商 (IdP)(日志 (Logto))。一旦用户登录到一个应用程序,当用户访问另一个应用程序时,Logto 将自动完成登录过程。

要了解有关基于重定向的登录的原理和好处的更多信息,请参阅 Logto 登录体验解释


在开始之前,你需要在管理控制台中为你的应用程序添加一个重定向 URI。

让我们切换到 Logto Console 的应用详情页面。添加一个重定向 URI io.logto://callback 并点击“保存更改”。

Logto Console 中的重定向 URI
  • 对于 iOS,重定向 URI 方案并不重要,因为 ASWebAuthenticationSession 类会监听重定向 URI,无论它是否已注册。
  • 对于 Android,重定向 URI 方案必须在 AndroidManifest.xml 文件中注册。

配置重定向 URI 后,我们在页面上添加一个登录按钮,该按钮将调用 logtoClient.signIn API 来启动 Logto 登录流程:

lib/main.dart
class _MyHomePageState extends State<MyHomePage> {
// ...
final redirectUri = 'io.logto://callback';


Widget build(BuildContext context) {
// ...

Widget signInButton = TextButton(
onPressed: () async {
await logtoClient.signIn(redirectUri);
render();
},
child: const Text('Sign In'),
);

return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SelectableText('My Demo App'),
signInButton,
],
),
),
);
}
}

实现登出

现在让我们在主页上添加一个登出按钮,以便用户可以从你的应用程序中登出。

lib/main.dart
class _MyHomePageState extends State<MyHomePage> {
// ...


Widget build(BuildContext context) {
// ...

Widget signOutButton = TextButton(
onPressed: () async {
await logtoClient.signOut();
render();
},
child: const Text('Sign Out'),
);

return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SelectableText('My Demo App'),
signInButton,
signOutButton,
],
),
),
);
}
}

处理认证状态

Logto SDK 提供了一个异步方法来检查认证状态。该方法是 logtoClient.isAuthenticated。如果用户已认证,该方法返回布尔值 true,否则返回 false

在示例中,我们根据认证状态有条件地渲染登录和登出按钮。现在让我们更新 Widget 中的 render 方法来处理状态变化:

lib/main.dart
class _MyHomePageState extends State<MyHomePage> {
// ...
bool? isAuthenticated = false;

void render() {
setState(() async {
isAuthenticated = await logtoClient.isAuthenticated;
});
}


Widget build(BuildContext context) {
// ...

return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SelectableText('My Demo App'),
isAuthenticated == true ? signOutButton : signInButton,
],
),
),
);
}
}

检查点:测试你的应用程序

现在,你可以测试你的应用程序:

  1. 运行你的应用程序,你将看到登录按钮。
  2. 点击登录按钮,SDK 将初始化登录过程并将你重定向到 Logto 登录页面。
  3. 登录后,你将被重定向回你的应用程序,并看到登出按钮。
  4. 点击登出按钮以清除令牌存储并登出。

添加 Discord 连接器

要实现快速登录并提高用户转化率,请将 Flutter 作为身份提供商 (IdP) 进行连接。Logto 社交连接器可以帮助你在几分钟内通过允许输入多个参数来建立此连接。

要添加社交连接器,只需按照以下步骤操作:

  1. 导航到 Console > Connectors > Social Connectors
  2. 点击“添加社交连接器”并选择“Discord”。
  3. 按照 README 指南完成必填字段并自定义设置。

Connector tab

备注:

如果你正在按照现场连接器指南进行操作,可以跳过下一部分。

设置 Discord OAuth 应用

注册开发者应用程序

  • 访问 Discord Developer Portal 并使用你的 Discord 账户登录。
  • 点击 New Application 按钮创建一个应用程序,为其选择一个名称(例如:LogtoAuth),勾选框并点击 Create
  • 转到 OAuth2 页面并点击 Reset Secret
  • 记录下 CLIENT IDCLIENT SECRET 字段
  • 添加有效的重定向(例如:http://auth.mycompany.io/callback/${connector_id})。connector_id 可以在 Logto 管理控制台连接器详情页面的顶部栏找到。

配置 Logto

配置类型

名称类型
clientIdstring
clientSecretstring
scopestring

clientId

clientId 是我们之前保存的 CLIENT ID 字段。 (你可以在 Discord Developer Portal 的 OAuth2 页面找到它。)

clientSecret

clientSecret 是我们之前保存的 CLIENT SECRET。 (如果你丢失了它,你需要点击 Reset Secret。)

scope

scope 是用户授权授予的权限。默认值是 identify email。 你可以在 这里 查看完整的权限列表。

保存你的配置

仔细检查你是否在 Logto 连接器配置区域填写了必要的值。点击“保存并完成”(或“保存更改”),Discord 连接器现在应该可用了。

在登录体验中启用 Discord 连接器

一旦你成功创建了一个社交连接器,你可以在登录体验中将其启用为“继续使用 Discord”按钮。

  1. 导航到 Console > 登录体验 > 注册和登录
  2. (可选)如果只需要社交登录,选择“无”作为注册标识符。
  3. 将配置好的 Discord 连接器添加到“社交登录”部分。

登录体验选项卡

测试和验证

返回到你的 Flutter 应用。你现在应该可以使用 Discord 登录了。享受吧!

拓展阅读

终端用户流程:Logto 提供开箱即用的认证 (Authentication) 流程,包括多因素认证 (MFA) 和企业单点登录 (SSO),以及强大的 API,用于灵活实现账户设置、安全验证和多租户体验。

授权 (Authorization):授权 (Authorization) 定义了用户在被认证 (Authentication) 后可以执行的操作或访问的资源。探索如何保护你的 API 以用于原生和单页应用程序,并实现基于角色的访问控制 (RBAC)。

组织 (Organizations):在多租户 SaaS 和 B2B 应用中特别有效,组织功能支持租户创建、成员管理、组织级 RBAC 和即时供应。

客户 IAM 系列:我们关于客户(或消费者)身份和访问管理的系列博客文章,从 101 到高级主题及更深入的内容。