Flutter集成DFNS服务插件dfns_sdk_flutter的使用

Flutter集成DFNS服务插件dfns_sdk_flutter的使用

Dfns Flutter SDK

欢迎,开发者们 👋🔑 这个仓库包含了Dfns Flutter SDK。以下是相关链接:


BETA警告

⚠️ 注意:该项目目前处于BETA阶段。

这意味着虽然我们已经努力确保其功能的完整性,但仍可能存在一些bug、性能问题或意外行为。


安装

在你的Flutter项目中添加插件:

flutter pub add dfns_sdk_flutter

概念

PasskeysSigner

所有对Dfns API的状态更改请求都需要使用与用户注册的凭据进行加密签名。

注意: 更准确地说,不是请求本身需要签名,而是由Dfns发出的“用户操作挑战”需要签名。为简化描述,我们将其称为“请求签名”。

此签名作为加密证明,确保只有授权实体才能发起请求。如果没有签名,请求将返回未授权错误。在实现Flutter应用时,您的后端服务器需要与Dfns API通信以获取此挑战,并将其传递给您的应用。PasskeysSigner 将用于注册和认证用户。

注册
final fido2Attestation = await PasskeysSigner.register(challenge);
登录
final fido2Assertion = await PasskeysSigner.sign(initRes.challenge);

DfnsDemo

一个使用SDK的示例应用可以在这里找到:示例应用。此示例应用需要与以下教程中的演示服务器配合使用:委托注册和登录教程


示例代码

以下是完整的示例代码,展示如何在Flutter中使用Dfns SDK。

import 'package:dfns_sdk_flutter_example/delegated_login.dart';
import 'package:dfns_sdk_flutter_example/delegated_registration.dart';
import 'package:dfns_sdk_flutter_example/wallets.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Dfns Flutter SDK Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String username = '';
  String token = '';

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: SingleChildScrollView(
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                // Logo
                const Center(
                  child: Image(
                    image: AssetImage('images/logo.png'),
                    width: 160,
                    height: 160,
                  ),
                ),

                // 引言
                Padding(
                  padding: const EdgeInsets.only(bottom: 16),
                  child: Text('引言',
                      style: Theme.of(context)
                          .textTheme
                          .titleLarge!
                          .copyWith(fontWeight: FontWeight.bold)),
                ),
                const Padding(
                    padding: EdgeInsets.only(bottom: 16),
                    child: Text(
                      '本教程应用程序演示了如何在以下配置中使用Dfns SDK:\n\n• 您有一个服务器和一个单页Web应用。\n• 您不是托管方,客户拥有自己的钱包。\n• 客户将使用WebAuthn(首选)或密钥凭据(不推荐,存在安全风险)来通过Dfns认证。\n• 客户端应用程序通过服务器与Dfns API通信,而不是直接调用API。\n• 您的服务器使用服务账户与Dfns API通信。',
                    )),

                // 第一步:委托注册
                Padding(
                  padding: const EdgeInsets.only(bottom: 16),
                  child: Text('步骤1 - 委托注册',
                      style: Theme.of(context)
                          .textTheme
                          .titleLarge!
                          .copyWith(fontWeight: FontWeight.bold)),
                ),
                const Padding(
                  padding: EdgeInsets.only(bottom: 16),
                  child: Text(
                    '您的客户,无论是新客户还是现有客户,都必须先在Dfns上注册并拥有系统中的凭证,以便拥有并能够与其区块链钱包交互。\n\n委托注册流允许您代表客户启动并完成注册过程,而他们不会意识到钱包基础设施是由Dfns支持的,即他们不会像正常员工注册流程那样收到Dfns的注册邮件。他们的WebAuthn凭据仍然完全由他们控制。',
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.only(bottom: 16),
                  child: SizedBox(
                    width: double.infinity,
                    child: ElevatedButton(
                        onPressed: () {
                          Navigator.of(context).push(
                            MaterialPageRoute(
                              builder: (context) =>
                                  DelegatedRegistration(callback: (String s) {
                                setState(() {
                                  username = s;
                                });
                              }),
                            ),
                          );
                        },
                        child: const Text('前往委托注册')),
                  ),
                ),

                // 第二步:委托登录
                Padding(
                  padding: const EdgeInsets.only(bottom: 16),
                  child: Text('步骤2 - 委托登录',
                      style: Theme.of(context)
                          .textTheme
                          .titleLarge!
                          .copyWith(fontWeight: FontWeight.bold)),
                ),
                const Padding(
                  padding: EdgeInsets.only(bottom: 16),
                  child: Text(
                    '委托签名流不需要最终用户使用WebAuthn凭据进行签名。登录可以在服务器端透明地执行,并获得只读访问令牌。例如,您的服务器可以选择在委托注册完成后自动登录用户。在此教程中,此步骤被明确展示,以便更清楚地演示交互方式。',
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.only(bottom: 16),
                  child: SizedBox(
                    width: double.infinity,
                    child: ElevatedButton(
                        onPressed: () {
                          Navigator.of(context).push(
                            MaterialPageRoute(
                              builder: (context) => DelegatedLogin(
                                  username: username,
                                  callback: (String s) {
                                    setState(() {
                                      token = s;
                                    });
                                  }),
                            ),
                          );
                        },
                        child: const Text('前往委托登录')),
                  ),
                ),

                // 第三步:钱包
                Padding(
                  padding: const EdgeInsets.only(bottom: 16),
                  child: Text('步骤3 - 钱包',
                      style: Theme.of(context)
                          .textTheme
                          .titleLarge!
                          .copyWith(fontWeight: FontWeight.bold)),
                ),
                const Padding(
                  padding: EdgeInsets.only(bottom: 16),
                  child: Text(
                    '一旦登录成功,终端用户就可以使用他们拥有的钱包。',
                  ),
                ),
                if (token.isNotEmpty)
                  Padding(
                    padding: const EdgeInsets.only(bottom: 16),
                    child: SizedBox(
                      width: double.infinity,
                      child: ElevatedButton(
                          onPressed: () {
                            Navigator.of(context).push(
                              MaterialPageRoute(
                                builder: (context) => Wallets(
                                  token: token,
                                ),
                              ),
                            );
                          },
                          child: const Text('前往钱包')),
                    ),
                  ),
                if (token.isEmpty)
                  const Padding(
                    padding: EdgeInsets.only(bottom: 16),
                    child: Text('⚠️ 您需要先完成步骤1和步骤2'),
                  ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

更多关于Flutter集成DFNS服务插件dfns_sdk_flutter的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter集成DFNS服务插件dfns_sdk_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


要在Flutter项目中集成DFNS服务插件 dfns_sdk_flutter,你可以按照以下步骤进行操作。这个插件通常用于与DFNS的后端服务进行交互,实现诸如身份验证、钱包管理等功能。

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 dfns_sdk_flutter 插件的依赖。

dependencies:
  flutter:
    sdk: flutter
  dfns_sdk_flutter: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来获取依赖。

2. 初始化DFNS SDK

在你的Flutter应用程序中,通常需要在应用启动时初始化DFNS SDK。你可以在 main.dart 文件中进行初始化。

import 'package:dfns_sdk_flutter/dfns_sdk_flutter.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // 初始化DFNS SDK
  await DfnsSdkFlutter.initialize(
    apiUrl: 'https://api.dfns.io', // DFNS API URL
    appId: 'your-app-id',          // 你的应用ID
    authToken: 'your-auth-token',  // 你的认证Token
  );

  runApp(MyApp());
}

3. 使用DFNS SDK

初始化完成后,你可以在应用的其他部分使用DFNS SDK提供的功能。例如,进行用户认证、创建钱包等操作。

import 'package:dfns_sdk_flutter/dfns_sdk_flutter.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('DFNS SDK Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              try {
                // 示例:创建一个新的钱包
                final wallet = await DfnsSdkFlutter.createWallet(
                  walletName: 'MyWallet',
                  network: 'Ethereum',
                );
                print('Wallet created: $wallet');
              } catch (e) {
                print('Error creating wallet: $e');
              }
            },
            child: Text('Create Wallet'),
          ),
        ),
      ),
    );
  }
}

4. 处理错误和异常

在使用DFNS SDK时,确保你正确处理了可能出现的错误和异常。你可以使用 try-catch 块来捕获和处理错误。

try {
  final wallet = await DfnsSdkFlutter.createWallet(
    walletName: 'MyWallet',
    network: 'Ethereum',
  );
  print('Wallet created: $wallet');
} catch (e) {
  print('Error creating wallet: $e');
}

5. 其他功能

DFNS SDK 通常还提供了其他功能,如签名交易、获取钱包信息等。你可以查阅 dfns_sdk_flutter 的官方文档或API参考来了解更多细节。

6. 调试和日志

在开发过程中,你可以启用调试日志来帮助排查问题。

DfnsSdkFlutter.setLogLevel(LogLevel.debug);
回到顶部