Flutter网络请求与安全防护插件datadome_flutter_dio的使用

发布于 1周前 作者 ionicwang 来自 Flutter

Flutter网络请求与安全防护插件datadome_flutter_dio的使用

概述

datadome_flutter_dio 是一个Flutter插件,用于支持使用Dio HTTP客户端的DataDome保护。该插件提供了一个拦截器,过滤和验证所有请求以确保您的应用网络层受到DataDome的保护。显示验证码、管理Cookie和处理事件跟踪都由插件管理。

安装插件

要安装插件,请运行以下命令:

flutter pub add datadome_flutter_dio

注意: 确保您的项目支持Swift/Kotlin。如果不支持,可以通过以下命令启用Swift/Kotlin:

# Replace project_name with your project's directory name
flutter create -i swift -a kotlin project_name

使用方法

导入DataDome拦截器

您可以使用以下语句导入DataDome拦截器类:

import 'package:datadome_flutter_dio/datadome_interceptor.dart';

初始化DataDome拦截器

确保通过传递以下参数创建DataDome拦截器实例:

  • DataDome客户端密钥
  • Dio客户端
  • 用于显示验证码的上下文

创建后,可以将拦截器添加到Dio:

var dio = Dio();
dio.interceptors.add(DataDomeInterceptor('YOUR_CLIENT_SIDE_KEY', dio, context));

强制显示验证码

为了测试和验证集成,可以使用特定的头信息来强制DataDome远程保护模块阻止请求并强制插件显示验证码。我们使用User-Agent头信息值为BLOCKUA来提示远程模块阻止请求。请注意,验证码仅显示一次,然后生成的Cookie将被本地存储。

以下是执行GET请求时强制显示验证码的示例代码:

var dio = Dio();
dio.interceptors.add(DataDomeInterceptor('YOUR_CLIENT_SIDE_KEY', dio, context));
try {
  var response = await dio.get(
    'https://datadome.co/wp-json', 
    options: Options(headers: {'User-Agent': 'BLOCKUA'})
  );
  print(response);
} catch (e) {
  print(e);
}

重要提示: 不要在生产环境中保留此头信息。这将导致所有用户至少看到一次验证码。

配置日志记录

datadome_flutter_dio 插件附带了一个日志记录器。您可以根据以下日志级别配置日志记录器以将日志消息打印到控制台:

默认情况下,插件处于静默模式(日志级别为none)。

级别 描述
verbose 记录所有内容
info 记录信息消息、警告和错误
warning 仅记录警告和错误消息
error 仅记录错误
none 静默模式(默认)

设置日志级别的语法如下:

DataDomeLogger.setLogLevel(LogLevel.warning);

手动集成

如果需要对验证码页面的显示进行更精细的控制,可以使用手动集成模式。验证码显示和关闭事件将通过回调函数传递,并在初始化DataDomeInterceptor.withCallback函数时作为参数传递。

DataDomeInterceptor dataDomeInterceptor = DataDomeInterceptor.withCallback(datadome_client_key, dio, (widget) { displayCaptcha(widget); }, () { dismissCaptcha(); });

以下是验证码页面显示和关闭回调函数的示例:

void displayCaptcha(Widget view) {
  showGeneralDialog(
    context: context,
    barrierDismissible: false,
    pageBuilder: (context, __, ___) {
      return view;
    },
  );
}

void dismissCaptcha() {
  Navigator.pop(context);
}

在原生和WebView之间共享Cookie

如果您的应用程序同时使用原生页面和WebView页面,建议在两者之间共享DataDome Cookie。这将避免用户每次切换到WebView页面时丢失与DataDome的会话。

从原生到WebView

首先使用getDataDomeCookie方法检索存储的DataDome Cookie:

String cookieValue = await dataDomeInterceptor.getDataDomeCookie();

然后将此Cookie值添加到您的Cookie管理器中。假设使用webview_cookie_manager包中的WebviewCookieManager

// Get stored DataDome cookie
String cookieValue = await dataDomeInterceptor.getDataDomeCookie();

var wvCookie = Cookie.fromSetCookieValue(cookieValue);
// Add DataDome cookie to cookie manager
await cookieManager.setCookies([wvCookie], origin: test_url);

从WebView到原生

从WebView中存储新的DataDome Cookie值:

final cookies = await cookieManager.getCookies(url);
for (var item in cookies) {
  if(item.name == "datadome") {
    // Update DataDome cookie store with the new cookie value.
    dataDomeInterceptor.setDataDomeCookie(item.toString());
  }
}

示例Demo

以下是完整的示例代码,展示了如何使用datadome_flutter_dio插件进行网络请求和验证码显示:

import 'package:datadome_flutter_dio/datadome_logger.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  var dio = Dio();
  late DataDomeInterceptor dataDomeInterceptor;

  @override
  void initState() {
    super.initState();
    DataDomeLogger.setLogLevel(LogLevel.info);
    initPlatformState();
  }

  Future<void> initPlatformState() async {
    if (!mounted) return;
  }

  Future<void> sendRequest() async {
    dataDomeInterceptor = DataDomeInterceptor('YOUR_CLIENT_SIDE_KEY', dio, context);
    dio.interceptors.add(dataDomeInterceptor);

    try {
      var response = await dio.get(
        'https://datadome.co/wp-json', 
        options: Options(headers: {'User-Agent': 'BLOCKUA'})
      );
      print(response);
    } catch (e) {
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('DataDome Example App'),
        ),
        body: Center(
          child: Column(
            children: <Widget>[
              MaterialButton(
                child: Text(
                  'Send Request',
                  style: TextStyle(fontSize: 20.0),
                ),
                color: Colors.blueAccent,
                textColor: Colors.white,
                onPressed: () {
                  sendRequest();
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

以上示例展示了如何在Flutter应用中使用datadome_flutter_dio插件进行网络请求,并在必要时显示验证码。请确保替换YOUR_CLIENT_SIDE_KEY为您自己的DataDome客户端密钥。


更多关于Flutter网络请求与安全防护插件datadome_flutter_dio的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter网络请求与安全防护插件datadome_flutter_dio的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter中使用datadome_flutter_dio插件进行网络请求与安全防护的示例代码。这个插件结合了dio库进行网络请求,并集成了Datadome的安全防护功能。

首先,确保你已经添加了必要的依赖到你的pubspec.yaml文件中:

dependencies:
  flutter:
    sdk: flutter
  dio: ^4.0.0  # 确保使用兼容版本的dio
  datadome_flutter_dio: ^最新版本号  # 请替换为实际的最新版本号

然后,运行flutter pub get来安装依赖。

接下来,在你的Flutter项目中创建一个服务来管理网络请求。以下是一个示例:

import 'package:dio/dio.dart';
import 'package:datadome_flutter_dio/datadome_flutter_dio.dart';
import 'package:flutter/material.dart';

// 创建一个Datadome拦截器
final datadomeInterceptor = DatadomeInterceptor(
  apiKey: '你的Datadome API密钥',  // 请替换为你的实际API密钥
  configurationId: '你的Datadome配置ID',  // 请替换为你的实际配置ID
);

// 创建一个Dio实例并添加Datadome拦截器
final dio = Dio(
  BaseOptions(
    baseUrl: 'https://你的API基础URL',  // 请替换为你的实际API基础URL
    headers: {
      'Content-Type': 'application/json',
    },
  ),
)
  ..interceptors.add(datadomeInterceptor)
  ..interceptors.add(
    InterceptorsWrapper(
      onRequest: (options, handler) {
        // 在这里可以添加其他请求前的处理逻辑
        return handler.next(options);
      },
      onResponse: (response, handler) {
        // 在这里可以添加对响应的处理逻辑
        return handler.next(response);
      },
      onError: (err, handler) {
        // 在这里可以添加对错误的处理逻辑
        return handler.next(err);
      },
    ),
  );

class ApiService {
  // 示例:获取用户信息
  Future<Map<String, dynamic>> getUserInfo(String userId) async {
    try {
      Response<Map<String, dynamic>> response = await dio.get('/users/$userId');
      return response.data;
    } catch (e) {
      // 处理网络错误
      throw e;
    }
  }
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Datadome Flutter DIO 示例'),
        ),
        body: Center(
          child: FutureBuilder<Map<String, dynamic>>(
            future: ApiService().getUserInfo('123'),  // 替换为实际的用户ID
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                if (snapshot.hasError) {
                  return Text('Error: ${snapshot.error}');
                } else {
                  return Text('User Info: ${snapshot.data}');
                }
              } else {
                return CircularProgressIndicator();
              }
            },
          ),
        ),
      ),
    );
  }
}

在这个示例中:

  1. 我们创建了一个DatadomeInterceptor实例,并传入了Datadome的API密钥和配置ID。
  2. 我们创建了一个Dio实例,并添加了Datadome拦截器以及其他可能的拦截器(如请求、响应和错误处理)。
  3. 我们定义了一个ApiService类,其中包含一个getUserInfo方法,用于从API获取用户信息。
  4. MyApp组件中,我们使用FutureBuilder来异步获取用户信息,并在UI中显示结果或错误信息。

请注意,你需要在Datadome控制台中为你的应用获取实际的API密钥和配置ID,并替换示例代码中的占位符。此外,确保你的API基础URL是正确的,并且API端点(如/users/$userId)是存在的。

这个示例代码提供了一个基本的框架,你可以根据实际需求进行扩展和修改。

回到顶部