Flutter证书锁定网络请求插件certificate_pinning_httpclient的使用
Flutter证书锁定网络请求插件 certificate_pinning_httpclient
的使用
certificate_pinning_httpclient
是一个实现了带有证书锁定功能的 HttpClient
插件。锁定是基于 SPKI(主题公钥信息)SHA-256 哈希值进行的。客户端将通过 MethodChannel 下载证书并缓存它们,所有与 SPKI 哈希匹配的证书将用于 SecurityContext。
使用方法
获取 SPKI 哈希值
客户端会记录每个证书链中的 SPKI 哈希值。你可以使用这些哈希值来配置你的应用。你也可以通过 GnuTLS 来获取哈希值:gnutls-cli --print-cert example.com
(查找 Public Key PIN)。
示例代码
使用 http
包
import 'package:certificate_pinning_httpclient/certificate_pinning_httpclient.dart';
import 'package:http/io_client.dart';
final client = IOClient(CertificatePinningHttpClient(
["S4kZuhQQ1DPcMOCYFQXD0gG+UW0zmyVx6roNWpRl65I="]));
使用 Dio
包
import 'package:certificate_pinning_httpclient/certificate_pinning_httpclient.dart';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';
final _dio = Dio();
(_dio.httpClientAdapter as IOHttpClientAdapter).onHttpClientCreate =
(client) => CertificatePinningHttpClient(
["S4kZuhQQ1DPcMOCYFQXD0gG+UW0zmyVx6roNWpRl65I="]);
禁用日志(适用于发布版本)
import 'package:logger/logger.dart';
Logger.level = kDebugMode ? Level.debug : Level.nothing;
完整示例 Demo
以下是一个完整的 Flutter 应用示例,展示了如何使用 certificate_pinning_httpclient
插件:
import 'package:certificate_pinning_httpclient/certificate_pinning_httpclient.dart';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:flutter/material.dart';
import 'package:http/io_client.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Certificate Pinning Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _httpStatus = 0;
int _dioStatus = 0;
String _httpError = "";
String _dioError = "";
static const String exampleComSpki =
"Xs+pjRp23QkmXeH31KEAjM1aWvxpHT6vYy+q2ltqtaM="; // 可能过期
final _http = IOClient(CertificatePinningHttpClient([exampleComSpki]));
final _dio = Dio();
_MyHomePageState() {
(_dio.httpClientAdapter as IOHttpClientAdapter).onHttpClientCreate =
(client) => CertificatePinningHttpClient([exampleComSpki]);
}
Future<void> _makeHttpCall(String url) async {
int httpStatus = -1;
int dioStatus = -1;
String? httpError;
String? dioError;
try {
httpStatus = (await _http.get(Uri.parse(url))).statusCode;
} catch (err) {
httpError = err.toString();
}
try {
dioStatus = (await _dio.get(url)).statusCode!;
} catch (err) {
dioError = err.toString();
}
setState(() {
_httpStatus = httpStatus;
_dioStatus = dioStatus;
_httpError = httpError ?? "";
_dioError = dioError ?? "";
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
onPressed: () {
_makeHttpCall("https://example.com");
},
child: const Text("GET example.com"),
),
TextButton(
onPressed: () {
_makeHttpCall("https://pub.dev");
},
child: const Text("GET pub.dev (with invalid pins)"),
),
const SizedBox(height: 20),
Text('Http status from http client: $_httpStatus'),
Text('Http status from dio client: $_dioStatus'),
const SizedBox(height: 20),
if (_httpError.isNotEmpty)
Text("Error from http client: $_httpError"),
const SizedBox(height: 20),
if (_dioError.isNotEmpty) Text("Error from dio client: $_dioError"),
],
),
),
);
}
}
致谢
感谢 Approov 提供的基础工作。
更多关于Flutter证书锁定网络请求插件certificate_pinning_httpclient的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter证书锁定网络请求插件certificate_pinning_httpclient的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用certificate_pinning_httpclient
插件来实现证书锁定的示例代码。certificate_pinning_httpclient
插件允许你通过预定义的证书来实现HTTPS请求的证书锁定,以提高应用的安全性。
步骤 1: 添加依赖
首先,你需要在pubspec.yaml
文件中添加certificate_pinning_httpclient
依赖:
dependencies:
flutter:
sdk: flutter
certificate_pinning_httpclient: ^x.y.z # 请替换为最新版本号
然后运行flutter pub get
来安装依赖。
步骤 2: 配置证书
将你需要锁定的证书(通常是.pem格式)放置在你的Flutter项目的assets
目录下。确保在pubspec.yaml
中声明这些资产:
flutter:
assets:
- assets/your_certificate.pem
步骤 3: 使用插件进行网络请求
以下是一个完整的示例,展示了如何使用certificate_pinning_httpclient
插件进行网络请求:
import 'package:flutter/material.dart';
import 'package:certificate_pinning_httpclient/certificate_pinning_httpclient.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Certificate Pinning Example'),
),
body: Center(
child: CertificatePinningExample(),
),
),
);
}
}
class CertificatePinningExample extends StatefulWidget {
@override
_CertificatePinningExampleState createState() => _CertificatePinningExampleState();
}
class _CertificatePinningExampleState extends State<CertificatePinningExample> {
String responseData = '';
@override
void initState() {
super.initState();
_fetchData();
}
Future<void> _fetchData() async {
try {
// 创建CertificatePinningHttpClient实例
final client = CertificatePinningHttpClient.create(
pinnedCertificates: [
'assets/your_certificate.pem' // 替换为你的证书路径
],
trustAllCertificates: false, // 不信任所有证书,只信任列出的证书
);
// 使用创建的客户端进行GET请求
final response = await client.get(Uri.parse('https://your-api-endpoint.com/data'));
// 检查响应状态并读取数据
if (response.statusCode == 200) {
setState(() {
responseData = response.body;
});
} else {
setState(() {
responseData = 'Failed to fetch data: ${response.statusCode}';
});
}
} catch (e) {
setState(() {
responseData = 'Error: $e';
});
}
}
@override
Widget build(BuildContext context) {
return Text(responseData);
}
}
注意事项
- 证书路径:确保
pinnedCertificates
中的证书路径正确无误。 - 错误处理:在真实应用中,应添加更多的错误处理逻辑,例如重试机制、超时处理等。
- 安全性:不要在生产环境中使用
trustAllCertificates: true
,这会绕过所有证书验证,降低安全性。
通过上述步骤,你应该能够在Flutter项目中成功使用certificate_pinning_httpclient
插件来实现证书锁定的网络请求。