Flutter身份验证插件sbt_auth_dart的使用
Flutter身份验证插件sbt_auth_dart的使用
SBTAuth SDK for flutter.
Setup
iOS
在 Info.plist 文件中添加自定义 URL 方案。
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLSchemes</key>
<array>
<string>{your custom scheme}</string>
</array>
</dict>
</array>
Android
在 AndroidManifest.xml 文件中添加 intent-filter 内部的 activity。
<activity ...>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="{your custom scheme}" />
</intent-filter>
</activity>
初始化 SBTAuth
注意:如果 developMode
为 true
,则连接至测试服务,测试服务邮箱登录无需验证码,同时测试服务仅可连接至测试网。请在正式发布时确保 developMode
为 false
。
SBTAuth Wallet 目前支持网络包括 Ethereum, Polygon, BNB Smart Chain。
// 初始化 SBTAuth 前需要先调用 initHive 方法,一般放在 main.dart 中
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SbtAuth.initHive();
runApp(const MyApp());
}
// 初始化 sbtAuth
SbtAuth auth = SbtAuth(developMode: true, clientId: 'Demo', scheme: 'Custom scheme');
登录 SBTAuth 账户
SBTAuth 目前支持邮箱登录、Google Account、Facebook、Twitter。 如果使用邮箱验证码登录,需要先获取验证码。
// 传入邮箱 email 发送验证码
await auth.api.sendVerifyCode(email);
// 使用邮箱登录,传入邮箱 email,然后传入验证码 code 或者密码 password 进行登录
await auth.login(LoginType.email, {email: 'example@gmail.com', code: '121212'});
// 使用第三方登录,只需要传入 LoginType
await auth.login(LoginType.google);
登录成功后会获取用户信息,如果是新用户会直接创建账户进入 APP,可以设置登录密码, 并且设置安全码,得到加密后的私钥碎片, 支持发送加密碎片到邮箱。
if (auth.user?.backupPrivateKey != null) {
// 说明是新注册用户,推荐此时提醒用户通过邮箱备份。备份私钥时需用户输入安全密码,安全密码用于对私钥进行加密,保证备份私钥安全。
// 传入密码 password 来设置账户的登录密码, 同时可以设置支付密码 paymentPassword, paymentSwitch 表示是否开启密码
await auth.api.setPassword(password, paymentPassword: "123456", paymentSwitch: true);
// 如果用户开启了支付密码(auth.user.paymentSwitch == true), 那么交易之前需要先验证支付密码 paymentPassword, 验证密码正确后再发起交易
await auth.api.checkPaymentPassword(paymentPassword);
// 传入加密的私钥碎片 encryptPrivateKey, 邮箱 email,和邮箱验证码 code 来发送备份的私钥碎片
// chan 为备份的碎片的链, 不传默认为 EVM
await auth.sendBackupPrivateKey(encryptPrivateKey, email, code, chain: chain);
}
如果是已注册用户,并且在新设备登录,则需要恢复私钥碎片,可以通过已登录设备授权的方式恢复,也可以通过原来备份的私钥碎片进行恢复。
已登录设备授权恢复
// 需要先获取已登录设备列表
final deviceList = await auth.api.getUserDeviceList();
// 从列表中选择设备,传入设备名 deviceName, 需要恢复的链 chain 调用方法来请求已登录设备授权
await auth.api.sendAuthRequest(deviceName, chain: chain);
// 输入已登录设备生成的授权码 code, 要恢复的链 chain 获取授权完成恢复
await auth.recoverWithDevice(code, chain: chain);
通过保存的私钥碎片恢复
// chain 表示需要恢复的链, 不传默认恢复 EVM
await auth.recoverWidthBackup(backupPrivateKey, password, chain: chain);
已登录设备在账户登录之后,或者在 APP 初始化且账户登录未过期时添加监听。
sbtAuth.authRequestStreamController.stream.listen((event) {
// 获取新设备名 deviceName
final deviceName = jsonDecode(event)['deviceName'];
// 获取请求授权恢复的链 keyType
final keyType = jsonDecode(event)['keyType'];
// 获取新设备名称后传入得到的设备名 deviceName, 链名 keyType 需要生成授权码授权新设备登录
final authCode = await sbtAuth.approveAuthRequest(deviceName, chain: SbtChain.values.byName(keyType));
});
使用 SBTAuth 钱包
调用 personal_sign
方法对消息进行签名
final provider = auth.provider;
// 传入要签名的数据 message 来获取签名
final signature = await provider.request(RequestArgument(method: 'personal_sign', params: [message]));
发送交易
EVM
/// EVM
final provider = auth.provider;
// 发送交易之前首先要设置 chainId 如:'0x5'
provider.setChainId(chainId);
// 传入交易的信息之后调用 sendTransaction() 方法即可获取交易 hash
final txHash = await provider.sendTransaction(
to: to,
value: value,
data: data,
gasPrice: gasPrice
);
SOLANA
/// SOLANA
// Solana 的原生币和代币转账是不一样的, 代币转账需要先查询自己和收款方的代币关联账户, 并用自己的关联账户向对方关联账户转账代币,
// 如果收款方没有关联账户, 则需要先调用 createAssociatedTokenAccount() 方法给收款方创建关联账户
// 所有的交易只需要构造 Instruction 调用 sendTransaction() 方法来发送交易
final signer = sbtAuth.solanaSigner!;
// 转账需要传入构造的交易 instruction 和发送方 from
final hash = await signer.sendTransaction(instruction, from);
// 创建关联账户只需要传入交易发送方 from 交易接收方 to 以及代币地址 tokenAddress 即可
final hash = await signer.createAssociatedTokenAccount(from, to, tokenAddress);
// * 注意 创建关联账户 hash 需要上链成功之后才可以进行代币转账
BITCOIN
/// BITCOIN
final btcSigner = sbtAuth.bitcoinSigner!;
// Bitcoin 转账只需要传入交易发送方 from, 交易接收方 to 以及交易数量 amount 即可
// amount 不得小于 1000
final hash = await btcSigner.sendBtcTransaction(from, to, amount);
白名单相关功能
交易白名单是更高级的安全模式,开启白名单之后账户只能对白名单内的地址进行转账交易。
// 开启修改关闭等对白名单的操作都需要进行邮箱验证码验证,所以如果用户没有绑定邮箱,则需要提示用户先备份私钥并绑定邮箱
// 输入加密私钥的安全码 password, 邮箱 email, 邮箱验证码 code
await sbtAuth.sendBackupPrivateKey(password, email, code);
// 开启/关闭白名单
// 输入邮箱验证码 authCode, 白名单开启关闭状态 whitelistSwitch 来开启或关闭白名单
await sbtAuth.switchWhiteList(authCode, whitelistSwitch: whitelistSwitch);
// 获取白名单列表
// 可选参数 network, 输入即可查询对应网络的白名单列表, 不输即为所有网络的白名单列表
final whiteList = await sbtAuth.api.getUserWhiteList(page, pageSize, network: network);
// 获取单个白名单详情
// 输入白名单的 id userWhitelistID 来获取详情
final whiteListItem = await sbtAuth.api.getUserWhiteListItem(userWhitelistID);
// 新增白名单
// 输入邮箱验证码 authCode, 白名单地址 address, 白名单名称 name, 白名单网络 network 新增白名单地址, tolowerCase 表示是否需要小写, EVM 系需小写
await sbtAuth.createWhiteList(authCode, address, name, network, tolowerCase: false);
// 删除白名单
// 输入邮箱验证码 authCode, 白名单 id userWhitelistID 来删除白名单
await sbtAuth.deleteWhiteList(authCode, userWhitelistID);
// 修改白名单
// 输入邮箱验证码 authCode, 白名单地址 address, 白名单名称 name, 白名单 id userWhitelistID, 用户 id userId 和白名单网络 network 来修改白名单, tolowerCase 表示是否需要小写, EVM 系需小写
await sbtAuth.editWhiteList(authCode, address, name, userWhitelistID, userId, network, tolowerCase: true);
其他功能
可以设置登录有效期,延长或缩短登录过期时间。
// 只需要调用 setUserToken() 方法, 传入登录有效时间 tokenTime (单位:分钟)
await auth.api.setUserToken(tokenTime);
目前支持的网络以及网络名称 network
// 以太坊
ETH("eth", 1),
// 币安链
BSC("bsc", 56),
// Polygon
Polygon("polygon", 137),
// Solana
Solana("solana")
/// Bitcoin
Bitcoin("bitcoin")
// 以太坊测试网 Goerli
Goerli("eth_goerli", 5),
// 币安链测试网
BSC_test("bsc_chapel", 97),
// Polygon testnet
Polygon_test("polygon_mumbai", 80001),
// Solana devnet
Solana_devnet("solana_devnet")
// Bitcoin testnet
Bitcoin_testnet("btc_testnet")
示例代码
以下是完整的示例代码,展示了如何使用 sbt_auth_dart
插件进行身份验证和操作。
import 'dart:convert';
import 'dart:developer';
import 'package:example/confirm_auth.dart';
import 'package:example/grant_authorization.dart';
import 'package:example/sign.dart';
import 'package:flutter/material.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:sbt_auth_dart/sbt_auth_dart.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SbtAuth.initHive();
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(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
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> {
late TextEditingController _controller;
final sbtAuth = SbtAuth(developMode: true, clientId: 'Demo', scheme: 'sbtauth');
String code = '';
[@override](/user/override)
void initState() {
super.initState();
getCode();
_controller = TextEditingController();
_controller.text = '30min18@gmail.com';
sbtAuth.authRequestStreamController.stream.listen((event) {
if (event.contains('deviceName')) {
final deviceName = jsonDecode(event)['deviceName'];
final keyType = jsonDecode(event)['keyType'];
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ConfirmAuthPage(
deviceName: deviceName,
auth: sbtAuth,
keyType: keyType,
)));
}
});
sbtAuth.loginStreamController.stream.listen((event) {
if (event) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SignPage(
address: sbtAuth.user!.publicKeyAddress['EVM']['address'] ??
sbtAuth.core!.getAddress(isTestnet: sbtAuth.developMode),
sbtauth: sbtAuth,
),
),
);
}
});
}
getCode() async {
final res = await sbtAuth.getLoginQrCode();
setState(() {
code = res;
});
}
[@override](/user/override)
void dispose() {
_controller.dispose();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () async {
final res = await sbtAuth.getLoginQrCode();
setState(() {
code = res;
});
},
child: QrImageView(data: code),
),
TextField(
controller: _controller,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email',
),
),
ElevatedButton(
onPressed: () {
_login(LoginType.email, email: _controller.text.trim());
},
child: const Text('Login with email')),
ElevatedButton(
onPressed: () {
_login(LoginType.google);
},
child: const Text('Login with Google')),
ElevatedButton(
onPressed: () {
_login(LoginType.facebook);
},
child: const Text('Login With Facebook')),
ElevatedButton(
onPressed: () {
_login(LoginType.twitter);
},
child: const Text('Login With Twitter')),
],
),
),
),
);
}
_login(LoginType loginType, {String? email, String? password}) async {
try {
await sbtAuth.login(loginType,
email: email, code: '203687', password: password);
if (mounted) {
if (sbtAuth.provider == null) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GrantAuthorizationPage(
auth: sbtAuth,
)));
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SignPage(
address: sbtAuth.user!.publicKeyAddress['EVM'] == null
? sbtAuth.core!.getAddress(isTestnet: sbtAuth.developMode)
: sbtAuth.user!.publicKeyAddress['EVM']['address'],
sbtauth: sbtAuth,
),
),
);
}
}
} catch (e) {
if (e is SbtAuthException) {
log(e.toString());
if (e.toString() == 'New device detected') {}
}
}
}
}
更多关于Flutter身份验证插件sbt_auth_dart的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter身份验证插件sbt_auth_dart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
SbtAuthDart
是一个用于 Flutter 应用的身份验证插件,它提供了简单易用的 API 来处理用户登录、注册、注销等身份验证相关的功能。以下是如何在 Flutter 项目中使用 SbtAuthDart
插件的步骤。
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 sbt_auth_dart
插件的依赖。
dependencies:
flutter:
sdk: flutter
sbt_auth_dart: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 初始化插件
在使用 SbtAuthDart
插件之前,你需要在应用的入口处初始化它。通常是在 main.dart
文件中进行初始化。
import 'package:flutter/material.dart';
import 'package:sbt_auth_dart/sbt_auth_dart.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化 SbtAuthDart
await SbtAuthDart.initialize(
apiKey: 'YOUR_API_KEY', // 替换为你的 API Key
authDomain: 'YOUR_AUTH_DOMAIN', // 替换为你的认证域
);
runApp(MyApp());
}
3. 用户注册
你可以使用 SbtAuthDart
提供的 register
方法来注册新用户。
void registerUser() async {
try {
final user = await SbtAuthDart.register(
email: 'user@example.com',
password: 'password123',
);
print('User registered: ${user.email}');
} catch (e) {
print('Registration failed: $e');
}
}
4. 用户登录
使用 login
方法来登录用户。
void loginUser() async {
try {
final user = await SbtAuthDart.login(
email: 'user@example.com',
password: 'password123',
);
print('User logged in: ${user.email}');
} catch (e) {
print('Login failed: $e');
}
}
5. 用户注销
使用 logout
方法来注销当前用户。
void logoutUser() async {
try {
await SbtAuthDart.logout();
print('User logged out');
} catch (e) {
print('Logout failed: $e');
}
}
6. 获取当前用户
你可以使用 currentUser
方法来获取当前登录的用户。
void getCurrentUser() {
final user = SbtAuthDart.currentUser;
if (user != null) {
print('Current user: ${user.email}');
} else {
print('No user is currently logged in');
}
}
7. 监听身份验证状态
SbtAuthDart
还提供了身份验证状态变化的监听功能。
void listenToAuthState() {
SbtAuthDart.authStateChanges.listen((user) {
if (user != null) {
print('User is logged in: ${user.email}');
} else {
print('User is logged out');
}
});
}
8. 处理错误
在进行身份验证操作时,可能会遇到各种错误。SbtAuthDart
会抛出异常,你可以通过 try-catch
块来处理这些错误。
void handleErrors() async {
try {
await SbtAuthDart.login(
email: 'wrong@example.com',
password: 'wrongpassword',
);
} catch (e) {
print('Error: $e');
}
}