如何在Flutter中集成Google reCAPTCHA v2(不使用WebView)
在Flutter中不使用WebView集成Google reCAPTCHA V2的实现方案
Google官方未提供reCAPTCHA V2的Flutter原生SDK,但可以通过原生平台SDK结合MethodChannel或第三方封装包实现无WebView的集成,以下是具体步骤:
方法一:原生SDK + MethodChannel(自定义实现)
这种方式直接调用Android/iOS的原生reCAPTCHA验证能力,完全绕开WebView。
Android端配置
- 项目级
build.gradle添加Google Maven仓库:
allprojects { repositories { google() // 保留其他已有仓库 } }
- app级
build.gradle添加依赖:
dependencies { implementation 'com.google.android.gms:play-services-safetynet:18.0.1' }
AndroidManifest.xml添加网络权限:
<uses-permission android:name="android.permission.INTERNET" />
- 实现MethodChannel调用逻辑(在
MainActivity.kt中):
class MainActivity : FlutterActivity() { private val CHANNEL = "com.your.app/recaptcha" private val SITE_KEY = "你的reCAPTCHA站点密钥" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> if (call.method == "verify") { SafetyNet.getClient(this).verifyWithRecaptcha(SITE_KEY) .addOnSuccessListener { response -> response.tokenResult.takeIf { it.isNotEmpty() }?.let { result.success(it) } ?: result.error("EMPTY_TOKEN", "未获取到验证令牌", null) } .addOnFailureListener { e -> result.error("VERIFY_FAILED", e.message, null) } } else { result.notImplemented() } } } }
iOS端配置
Podfile添加依赖:
pod 'reCAPTCHA'
执行pod install更新依赖。
2. Info.plist添加网络权限配置:
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
- 实现MethodChannel调用逻辑(在
AppDelegate.swift中):
import UIKit import Flutter import reCAPTCHA @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { private let CHANNEL = "com.your.app/recaptcha" private let SITE_KEY = "你的reCAPTCHA站点密钥" private var recaptcha: ReCAPTCHA? override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { guard let controller = window?.rootViewController as? FlutterViewController else { return super.application(application, didFinishLaunchingWithOptions: launchOptions) } let channel = FlutterMethodChannel(name: CHANNEL, binaryMessenger: controller.binaryMessenger) recaptcha = try? ReCAPTCHA(siteKey: SITE_KEY, apiURL: URL(string: "https://www.google.com/recaptcha/api.js")!) channel.setMethodCallHandler { [weak self] call, result in guard let self = self, call.method == "verify" else { result.notImplemented() return } self.recaptcha?.verify(on: controller) { token in token != nil ? result.success(token) : result.error("VERIFY_FAILED", "验证失败", nil) } } GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } }
Flutter端调用
创建工具类封装MethodChannel调用:
import 'package:flutter/services.dart'; class RecaptchaManager { static const _channel = MethodChannel('com.your.app/recaptcha'); static Future<String?> verify() async { try { return await _channel.invokeMethod<String>('verify'); } on PlatformException catch (e) { print("reCAPTCHA验证错误: ${e.message}"); return null; } } }
在UI中触发验证:
ElevatedButton( onPressed: () async { final token = await RecaptchaManager.verify(); if (token != null) { // 将令牌发送到后端,用服务器密钥调用Google验证接口 print("获取到验证令牌: $token"); } else { // 处理验证失败逻辑 } }, child: const Text("完成reCAPTCHA验证"), )
方法二:使用第三方封装包
如果不想手动处理原生代码,可以选择维护状态良好的第三方包,比如flutter_recaptcha_native(封装了原生实现):
- 添加依赖到
pubspec.yaml:
dependencies: flutter_recaptcha_native: ^最新版本号
- 配置平台密钥:
- Android:在
AndroidManifest.xml添加元数据:
- Android:在
<meta-data android:name="com.google.android.recaptcha.site_key" android:value="你的站点密钥"/>
- iOS:在
Info.plist添加:
<key>RecaptchaSiteKey</key> <string>你的站点密钥</string>
- Flutter端调用:
import 'package:flutter_recaptcha_native/flutter_recaptcha_native.dart'; // 初始化 final recaptcha = FlutterRecaptchaNative(); // 触发验证 final token = await recaptcha.verify(); if (token != null) { // 发送到后端验证 }
关键注意事项
- 必须后端验证:客户端获取的令牌仅为临时凭证,必须发送到你的后端,使用服务器密钥调用
https://www.google.com/recaptcha/api/siteverify接口完成最终校验。 - 密钥配置:确保reCAPTCHA控制台中已正确配置你的Android包名和iOS Bundle ID,否则验证会被拒绝。
- 版本兼容:定期更新原生依赖版本,避免因API废弃导致的兼容性问题。
内容的提问来源于stack exchange,提问作者Mubasher Ansari
相关产品推荐
相关产品推荐

