Flutter SSL Pinning插件quixxi_ssl_pinning的使用

Flutter SSL Pinning插件quixxi_ssl_pinning的使用

Quixxi插件用于SSL Pinning。

开始使用

本项目是一个用于Flutter的插件包,包含Android和/或iOS平台的特定实现代码。

对于开始进行Flutter开发的帮助,可以查看在线文档,其中提供了教程、示例、移动开发指南以及完整的API参考。

示例代码

以下是一个完整的示例代码,演示了如何在Flutter应用中使用quixxi_ssl_pinning插件进行SSL Pinning:

import 'package:flutter/material.dart';
import 'dart:async';

import 'package:flutter/services.dart';
import 'package:quixxi_ssl_pinning/quixxi_ssl_pinning.dart';
import 'package:quixxi_ssl_pinning/quixxi_ssl_pinning_platform_interface.dart';

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

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

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _PiningSslData {
  String serverURL = '';
  Map<String, String> headerHttp = {};
  String allowedSHAFingerprint = '';
  int timeout = 0;
  SHA? sha;
}

class _MyAppState extends State<MyApp> {
  final _quixxiSslPinningPlugin = QuixxiSslPinning();
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final _PiningSslData _data = _PiningSslData();
  final _messengerKey = GlobalKey<ScaffoldMessengerState>();

  [@override](/user/override)
  void initState() {
    super.initState();
  }

  // 平台消息是异步的,因此我们在异步方法中初始化。
  check(
      String url,
      String fingerprint,
      SHA sha,
      Map<String, String> headerHttp,
      int timeout,
      ) async {
    List<String> allowedShA1FingerprintList = [];
    allowedShA1FingerprintList.add(fingerprint);

    try {
      // 平台消息可能会失败,所以我们使用一个try/catch来捕获PlatformException。
      String checkMsg = await QuixxiSslPinning().check(
          serverURL: url,
          headerHttp: headerHttp,
          sha: sha,
          allowedSHAFingerprints: allowedShA1FingerprintList,
          timeout: timeout);

      // 如果小部件从树中移除而异步平台消息仍在飞行,则我们希望丢弃回复而不是调用setState来更新我们的不存在的外观。
      if (!mounted) return;

      _messengerKey.currentState?.showSnackBar(
        SnackBar(
          content: Text(checkMsg),
          duration: const Duration(seconds: 1),
          backgroundColor: Colors.green,
        ),
      );
    } catch (e) {
      _messengerKey.currentState?.showSnackBar(
        SnackBar(
          content: Text(e.toString()),
          duration: const Duration(seconds: 1),
          backgroundColor: Colors.red,
        ),
      );
    }
  }

  void submit() {
    // 首先验证表单。
    if (_formKey.currentState?.validate() == true) {
      _formKey.currentState?.save(); // 现在保存我们的表单。

      check(
        _data.serverURL,
        _data.allowedSHAFingerprint,
        _data.sha ?? SHA.SHA256,
        _data.headerHttp,
        _data.timeout,
      );
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      scaffoldMessengerKey: _messengerKey,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Ssl Pinning Plugin'),
        ),
        body: Builder(
          builder: (BuildContext context) {
            return Container(
              padding: const EdgeInsets.all(20.0),
              child: Form(
                key: _formKey,
                child: ListView(
                  children: <Widget>[
                    TextFormField(
                      keyboardType: TextInputType.url,
                      controller:
                      TextEditingController(text: "https://randomuser.me/api/"),
                      decoration: const InputDecoration(
                        hintText: 'https://yourdomain.com',
                        labelText: 'URL',
                      ),
                      validator: (value) {
                        if (value?.isEmpty == true) {
                          return 'Please enter some url';
                        }
                        return null;
                      },
                      onSaved: (value) {
                        _data.serverURL = value ?? '';
                      },
                    ),
                    DropdownButton(
                      items: [
                        DropdownMenuItem(
                          child: Text(SHA.SHA1.toString()),
                          value: SHA.SHA1,
                        ),
                        DropdownMenuItem(
                          child: Text(SHA.SHA256.toString()),
                          value: SHA.SHA256,
                        )
                      ],
                      value: _data.sha,
                      isExpanded: true,
                      onChanged: (SHA? val) {
                        setState(() {
                          _data.sha = val;
                        });
                      },
                    ),
                    TextFormField(
                      controller: TextEditingController(
                          text:
                          "F1 CB F6 62 1F 6D 7C C3 DC 7B 31 ED A9 2D DA FE F0 2A E2 B2 EC 40 7F 32 A3 9F 6E 4F 7B 39 55 CE"),
                      keyboardType: TextInputType.text,
                      decoration: const InputDecoration(
                        hintText: 'OO OO OO OO OO OO OO OO OO OO',
                        labelText: 'Fingerprint',
                      ),
                      validator: (value) {
                        if (value?.isEmpty == null) {
                          return 'Please enter some fingerprint';
                        }
                        return null;
                      },
                      onSaved: (value) {
                        _data.allowedSHAFingerprint = value ?? '';
                      },
                    ),
                    TextFormField(
                      keyboardType: TextInputType.number,
                      initialValue: '60',
                      decoration: const InputDecoration(
                        hintText: '60',
                        labelText: 'Timeout',
                      ),
                      validator: (value) {
                        if (value?.isEmpty == true) {
                          return 'Please enter some timeout';
                        }
                        return null;
                      },
                      onSaved: (value) {
                        _data.timeout = int.tryParse(value ?? '') ?? 0;
                      },
                    ),
                    Container(
                      margin: const EdgeInsets.only(top: 20.0),
                      child: ElevatedButton(
                        onPressed: () => submit(),
                        child: const Text(
                          'Check',
                          style: TextStyle(
                            color: Colors.white,
                          ),
                        ),
                      ),
                    )
                  ],
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}

说明

  1. 初始化

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

    这里初始化了Flutter应用,并运行MyApp组件。

  2. 定义数据模型

    class _PiningSslData {
      String serverURL = '';
      Map<String, String> headerHttp = {};
      String allowedSHAFingerprint = '';
      int timeout = 0;
      SHA? sha;
    }
    

    定义了一个类来存储用户输入的数据。

  3. 检查函数

    check(
        String url,
        String fingerprint,
        SHA sha,
        Map<String, String> headerHttp,
        int timeout,
        ) async {
      List<String> allowedShA1FingerprintList = [];
      allowedShA1FingerprintList.add(fingerprint);
    
      try {
        String checkMsg = await QuixxiSslPinning().check(
            serverURL: url,
            headerHttp: headerHttp,
            sha: sha,
            allowedSHAFingerprints: allowedShA1FingerprintList,
            timeout: timeout);
        if (!mounted) return;
        _messengerKey.currentState?.showSnackBar(
          SnackBar(
            content: Text(checkMsg),
            duration: const Duration(seconds: 1),
            backgroundColor: Colors.green,
          ),
        );
      } catch (e) {
        _messengerKey.currentState?.showSnackBar(
          SnackBar(
            content: Text(e.toString()),
            duration: const Duration(seconds: 1),
            backgroundColor: Colors.red,
          ),
        );
      }
    }
    

    这个函数用于发起SSL Pinning检查,并根据结果显示相应的提示信息。

  4. 提交函数

    void submit() {
      if (_formKey.currentState?.validate() == true) {
        _formKey.currentState?.save();
        check(
          _data.serverURL,
          _data.allowedSHAFingerprint,
          _data.sha ?? SHA.SHA256,
          _data.headerHttp,
          _data.timeout,
        );
      }
    }
    

    提交表单并触发检查。

  5. 构建UI

    [@override](/user/override)
    Widget build(BuildContext context) {
      return MaterialApp(
        scaffoldMessengerKey: _messengerKey,
        home: Scaffold(
          appBar: AppBar(
            title: const Text('Ssl Pinning Plugin'),
          ),
          body: Builder(
            builder: (BuildContext context) {
              return Container(
                padding: const EdgeInsets.all(20.0),
                child: Form(
                  key: _formKey,
                  child: ListView(
                    children: <Widget>[
                      // 表单字段和按钮等...
                    ],
                  ),
                ),
              );
            },
          ),
        ),
      );
    }
    

更多关于Flutter SSL Pinning插件quixxi_ssl_pinning的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter SSL Pinning插件quixxi_ssl_pinning的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中实现SSL Pinning(SSL证书固定)是一种增强应用安全性的方法,它可以防止中间人攻击(MITM)。quixxi_ssl_pinning 是一个常用的Flutter插件,用于实现SSL Pinning。以下是如何使用 quixxi_ssl_pinning 插件的步骤:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 quixxi_ssl_pinning 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  quixxi_ssl_pinning: ^1.1.0

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

2. 初始化插件

在你的Flutter应用中,初始化 quixxi_ssl_pinning 插件。通常,你可以在 main.dart 文件中进行初始化。

import 'package:flutter/material.dart';
import 'package:quixxi_ssl_pinning/quixxi_ssl_pinning.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // Initialize the SSL Pinning plugin
  await QuixxiSslPinning.init();
  
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SSL Pinning Example',
      home: HomeScreen(),
    );
  }
}

3. 配置SSL Pinning

在初始化插件后,你需要配置SSL Pinning的证书。你可以将证书的公钥或证书的哈希值固定在应用中。

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('SSL Pinning Example'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            // Configure SSL Pinning
            await QuixxiSslPinning.configure(
              allowedFingerprints: [
                'SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', // Replace with your certificate's SHA256 fingerprint
              ],
              allowedPublicKeys: [
                'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', // Replace with your certificate's public key
              ],
            );
            
            // Make a secure request
            final response = await QuixxiSslPinning.makeSecureRequest(
              url: 'https://example.com',
              method: 'GET',
            );
            
            print('Response: $response');
          },
          child: Text('Make Secure Request'),
        ),
      ),
    );
  }
}

4. 获取证书的指纹或公钥

你可以使用以下命令来获取证书的SHA256指纹:

openssl x509 -in certificate.crt -noout -fingerprint -sha256

或者获取公钥:

openssl x509 -in certificate.crt -pubkey -noout

5. 处理响应

makeSecureRequest 方法中,你可以处理服务器的响应。如果证书验证失败,插件会抛出一个异常。

try {
  final response = await QuixxiSslPinning.makeSecureRequest(
    url: 'https://example.com',
    method: 'GET',
  );
  print('Response: $response');
} catch (e) {
  print('Error: $e');
}
回到顶部