Flutter SSL Pinning安全验证插件ssl_pinning_plugin的使用

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

Flutter SSL Pinning安全验证插件ssl_pinning_plugin的使用

ssl_pinning_plugin

此插件用于在HTTP请求中检查SSL Pinning。它通过比较已知的SHA-1或SHA-256指纹与目标服务器的SHA-1或SHA-256来确保连接的安全性。

入门指南

若要开始使用Flutter,请查看我们的在线文档

对于编辑插件代码的帮助,请参阅文档

检查方法

参数

  • serveurUrl : String * 必填
  • httpMethod : HttpMethod 枚举 [HttpMethod.Get || HttpMethod.Head] (默认值:HttpMethod.Get) * 必填
  • headerHttp : Map<String, String>
  • sha : SHA 枚举 [SHA.SHA1 || SHA.SHA256] * 必填
  • allowedSHAFingerprints : List<String>
  • timeout : int * 必填

使用方法:

await SslPinningPlugin.check(
  serverURL: url,
  httpMethod: HttpMethod.Get,
  headerHttp: new Map(),
  sha: SHA.SHA1,
  allowedSHAFingerprints: new List<String>,
  timeout: 50
);

返回值:

  • 成功时,返回字符串 “CONNECTION_SECURE”
  • 出错时,返回字符串 “CONNECTION_INSECURE”
  • 如果发生异常,则返回堆栈跟踪信息作为字符串值。

示例代码

下面是一个完整的示例应用,演示了如何使用ssl_pinning_plugin进行SSL Pinning检查。

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:ssl_pinning_plugin/ssl_pinning_plugin.dart';

void main() => runApp(MyApp());

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

class _PiningSslData {
  String serverURL = '';
  HttpMethod httpMethod = HttpMethod.Get;
  Map<String, String> headerHttp = Map();
  String allowedSHAFingerprint = '';
  int timeout = 0;
  late SHA sha = SHA.SHA1;
}

class _MyAppState extends State<MyApp> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  _PiningSslData _data = _PiningSslData();
  late BuildContext scaffoldContext;

  @override
  void initState() {
    super.initState();
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> check(String url, String fingerprint, HttpMethod httpMethod, SHA sha, Map<String, String> headerHttp, int timeout) async {
    List<String> allowedShA1FingerprintList = [];
    allowedShA1FingerprintList.add(fingerprint);

    try {
      // Platform messages may fail, so we use a try/catch PlatformException.
      String checkMsg = await SslPinningPlugin.check(
        serverURL: url,
        headerHttp: headerHttp,
        httpMethod: httpMethod,
        sha: sha,
        allowedSHAFingerprints: allowedShA1FingerprintList,
        timeout: timeout,
      );

      if (!mounted) return;

      ScaffoldMessenger.of(scaffoldContext).showSnackBar(
        SnackBar(
          content: Text(checkMsg),
          duration: Duration(seconds: 1),
          backgroundColor: Colors.green,
        ),
      );
    } catch (e) {
      ScaffoldMessenger.of(scaffoldContext).showSnackBar(
        SnackBar(
          content: Text(e.toString()),
          duration: Duration(seconds: 1),
          backgroundColor: Colors.red,
        ),
      );
    }
  }

  void submit() {
    if (_formKey.currentState!.validate()) {
      _formKey.currentState!.save();

      this.check(_data.serverURL, _data.allowedSHAFingerprint, _data.httpMethod, _data.sha, _data.headerHttp, _data.timeout);
    }
  }

  @override
  Widget build(BuildContext context) {
    this.scaffoldContext = context;
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Ssl Pinning Plugin'),
        ),
        body: Builder(builder: (BuildContext context) {
          this.scaffoldContext = context;
          return Container(
            padding: EdgeInsets.all(20.0),
            child: Form(
              key: this._formKey,
              child: ListView(
                children: <Widget>[
                  TextFormField(
                    keyboardType: TextInputType.url,
                    initialValue: "https://flutter.dev/",
                    decoration: InputDecoration(
                      hintText: 'https://yourdomain.com',
                      labelText: 'URL',
                    ),
                    validator: (value) {
                      if (value!.isEmpty) {
                        return 'Please enter some url';
                      }
                      return null;
                    },
                    onSaved: (value) => this._data.serverURL = value!,
                  ),
                  DropdownButton<SHA>(
                    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(() {
                        this._data.sha = val!;
                      });
                    },
                  ),
                  DropdownButton<HttpMethod>(
                    items: [
                      DropdownMenuItem(
                        child: Text(HttpMethod.Get.toString()),
                        value: HttpMethod.Get,
                      ),
                      DropdownMenuItem(
                        child: Text(HttpMethod.Head.toString()),
                        value: HttpMethod.Head,
                      )
                    ],
                    value: _data.httpMethod,
                    isExpanded: true,
                    onChanged: (HttpMethod? val) {
                      setState(() {
                        this._data.httpMethod = val!;
                      });
                    },
                  ),
                  TextFormField(
                    keyboardType: TextInputType.text,
                    initialValue: "9D B3 FC A9 17 36 04 27 A2 82 2F BD 06 95 F1 DC 0A 00 9F 72",
                    decoration: InputDecoration(
                      hintText: 'OO OO OO OO OO OO OO OO OO OO',
                      labelText: 'Fingerprint',
                    ),
                    validator: (value) {
                      if (value!.isEmpty) {
                        return 'Please enter some fingerprint';
                      }
                      return null;
                    },
                    onSaved: (value) => this._data.allowedSHAFingerprint = value!,
                  ),
                  TextFormField(
                    keyboardType: TextInputType.number,
                    initialValue: '60',
                    decoration: InputDecoration(
                      hintText: '60', 
                      labelText: 'Timeout'
                    ),
                    validator: (value) {
                      if (value!.isEmpty) {
                        return 'Please enter some timeout';
                      }
                      return null;
                    },
                    onSaved: (value) => this._data.timeout = int.parse(value!),
                  ),
                  Container(
                    margin: EdgeInsets.only(top: 20.0),
                    child: ElevatedButton(
                      child: Text('Check', style: TextStyle(color: Colors.white)),
                      onPressed: () => submit(),
                    ),
                  )
                ],
              ),
            ),
          );
        }),
      ),
    );
  }
}

这段代码创建了一个简单的Flutter应用程序,允许用户输入服务器URL、选择哈希算法(SHA-1或SHA-256)、HTTP方法(GET或HEAD)、提供指纹以及设置超时时间,并调用ssl_pinning_plugin来进行SSL Pinning检查。如果检查成功,将显示一个绿色的消息框,表示连接是安全的;如果有任何错误,则会显示红色的消息框并给出错误详情。


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

1 回复

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


当然,以下是如何在Flutter项目中使用ssl_pinning_plugin进行SSL Pinning安全验证的示例代码。这个插件允许你为你的应用实现证书固定,以增强通信安全性。

首先,确保你的Flutter项目中已经添加了ssl_pinning_plugin依赖。在pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  ssl_pinning_plugin: ^x.y.z  # 请替换为最新版本号

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

接下来,配置你的Flutter应用以使用ssl_pinning_plugin。以下是一个基本的示例,展示如何在HTTP请求中使用SSL Pinning。

  1. 导入插件

在你的Dart文件中导入ssl_pinning_plugin

import 'package:ssl_pinning_plugin/ssl_pinning_plugin.dart';
  1. 配置SSL Pinning

通常,你会在应用启动时配置SSL Pinning。例如,在main.dart中:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 配置SSL Pinning
  final SslPinningConfiguration sslPinningConfiguration = SslPinningConfiguration(
    // 你的证书文件的Base64编码字符串
    certificate: '''
      -----BEGIN CERTIFICATE-----
      ...(你的证书内容)...
      -----END CERTIFICATE-----
    ''',
    // 是否允许证书链中的证书过期(通常设置为false)
    allowInvalidCertificates: false,
    // 是否验证主机名(通常设置为true)
    validateHostname: true,
    // 是否允许自签名证书(通常设置为false)
    allowSelfSignedCertificates: false,
  );

  // 初始化SSL Pinning插件
  await SslPinningPlugin.initialize(sslPinningConfiguration);

  runApp(MyApp());
}

注意:上面的证书内容应该被替换为你的实际证书的Base64编码字符串。

  1. 使用HTTP请求

现在,当你进行HTTP请求时,SSL Pinning会自动生效。例如,使用http包:

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final SslPinningConfiguration sslPinningConfiguration = SslPinningConfiguration(
    certificate: '''
      -----BEGIN CERTIFICATE-----
      ...(你的证书内容)...
      -----END CERTIFICATE-----
    ''',
    allowInvalidCertificates: false,
    validateHostname: true,
    allowSelfSignedCertificates: false,
  );

  await SslPinningPlugin.initialize(sslPinningConfiguration);

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('SSL Pinning Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              try {
                final response = await http.get(Uri.parse('https://your-api-endpoint.com/data'));
                print('Response: ${response.body}');
              } catch (e) {
                print('Error: $e');
              }
            },
            child: Text('Fetch Data'),
          ),
        ),
      ),
    );
  }
}

在这个例子中,当你点击按钮时,应用会尝试从配置的HTTPS端点获取数据。如果证书不匹配或证书验证失败,请求将抛出异常。

注意

  • 在生产环境中,请确保你的证书是最新的,并且没有过期。
  • SSL Pinning增加了额外的安全性,但也意味着如果证书发生变化(例如证书续期),你需要更新应用中的证书。

这样,你就成功地在Flutter应用中配置了SSL Pinning安全验证。

回到顶部