如何使用MetaMask对Flutter应用进行身份认证?已试WalletConnect等库未果
Flutter 连接 MetaMask 实现登录认证方案
依赖配置
首先在pubspec.yaml中添加所需依赖:
dependencies: flutter: sdk: flutter walletconnect_flutter_v2: ^2.0.0 web3dart: ^2.7.0 crypto: ^3.0.3
初始化 WalletConnect V2 客户端
先去 WalletConnect 官网申请免费的ProjectID,然后初始化客户端:
import 'package:walletconnect_flutter_v2/walletconnect_flutter_v2.dart'; import 'package:web3dart/web3dart.dart'; import 'dart:convert'; import 'package:crypto/crypto.dart'; late Web3App _web3App; void initWalletConnect() async { _web3App = await Web3App.createInstance( projectId: '你的ProjectID', metadata: const PairingMetadata( name: '你的应用名称', description: 'MetaMask 登录认证', url: 'https://your-app-url.com', icons: ['https://your-app-url.com/icon.png'], ), ); }
连接 MetaMask 钱包
发起连接请求,指定目标链(示例用 Goerli 测试网,主网替换为eip155:1):
Future<String?> connectMetaMask() async { try { final session = await _web3App.connect( requiredNamespaces: { 'eip155': RequiredNamespace( chains: ['eip155:5'], methods: ['eth_accounts', 'personal_sign'], events: [], ), }, ); if (session != null) { final accounts = session.namespaces['eip155']?.accounts; if (accounts?.isNotEmpty == true) { // 提取以太坊地址格式 final addressHex = accounts!.first.split(':').last; return EthereumAddress.fromHex(addressHex).hexEip55; } } } catch (e) { print('连接失败:$e'); } return null; }
签名验证实现登录
通过让用户签名随机消息完成身份认证,防止重放攻击:
Future<bool> verifyLogin(String userAddress) async { final session = _web3App.activeSession; if (session == null) return false; // 生成带时间戳的随机消息 final loginMessage = '登录验证:${DateTime.now().millisecondsSinceEpoch}'; final messageBytes = utf8.encode(loginMessage); try { // 请求 MetaMask 签名 final signatureResult = await session.request( topic: session.topic, chainId: 'eip155:5', request: SessionRequestParams( method: 'personal_sign', params: [ bytesToHex(messageBytes, include0x: true), userAddress, ], ), ); if (signatureResult != null) { // 验证签名是否匹配用户地址 final signatureBytes = hexToBytes(signatureResult.toString().replaceFirst('0x', '')); final signerAddress = await EthereumAddress.fromHex(userAddress).verifySignature( messageBytes, signatureBytes, ); return signerAddress.hexEip55 == userAddress; } } catch (e) { print('签名验证失败:$e'); } return false; }
调用流程示例
在登录按钮的点击事件中串联逻辑:
void handleLoginTap() async { final address = await connectMetaMask(); if (address != null) { final isAuthenticated = await verifyLogin(address); if (isAuthenticated) { // 登录成功,跳转主页或保存用户信息 print('登录成功,账户:$address'); } else { // 签名无效,提示用户 print('身份验证失败'); } } else { // 连接失败,提示用户检查 MetaMask print('未成功连接 MetaMask'); } }
注意事项
- 移动端需配置 URL Scheme:Android 在
AndroidManifest.xml中添加<data android:scheme="metamask"/>;iOS 在Info.plist中添加CFBundleURLSchemes数组,包含metamask。 - 优先用测试网(如 Goerli)调试,避免主网资产风险。
- 确保用户已安装 MetaMask App(移动端)或浏览器插件(Web 端)。
内容的提问来源于stack exchange,提问作者cheo jose
相关产品推荐
相关产品推荐

