这里就不管是那个网络请求工具的第三方,直接操作HttpClient类来操作。
1.先说明双向验证的证书种类:
client_cert.pem 客户端证书(包含客户端公钥)
client_private.pem 客户端私钥
client_public.pem 客户端公钥
使用目的:验证客户端的合法性
sever_cert.pem 服务器证书(包含服务端公钥)
sever_public.pem 服务器端公钥 (存放在Client或者发送给Client)
sever_private.pem 服务器端私钥
使用目的:验证服务器端的合法性
.p12是证书和私钥的集合文件 带有密码:xxxx
2.客户端的配置
以Dio请求工具为例 客户端的配置 客户端的包里用到 服务器端公钥、客户端私钥、客户端的证书(包含公钥)这三个。(顺带提一句,Swift原生只需要服务器公钥和客户端的.p12文件就可以了)
List<int> caData = (await rootBundle.loadString("pubkey/sever_cert.pem")).buffer.asUint8List()
List<int> clientCertData = (await rootBundle.loadString("pubkey/client_cert.pem")).buffer.asUint8List()
List<int> clientPrivateData = (await rootBundle.loadString("pubkey/client_private.pem")).buffer.asUint8List()
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
SecurityContext sc = new SecurityContext(withTrustedRoots: true);
sc.setTrustedCertificatesBytes(caData); //设置服务器端的公钥,为了验证服务器端
sc.useCertificateChainBytes(clientCertData);//设置客户端证书到证书链
sc.usePrivateKeyBytes(clientPrivateData, password:'wiii');//设置私钥 虽然源码里的注释说pem不用密码,但是这里必须
HttpClient httpClient = new HttpClient(context: sc);
httpClient.badCertificateCallback=(X509Certificate cert, String host, int port){
return true;
};
return httpClient;
};
Dio校验证书
init(Dio dio) async {
ByteData data = await rootBundle.load('assets/certificate/certificate.crt');
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(client) {
SecurityContext securityContext = new SecurityContext();
securityContext.setTrustedCertificatesBytes(data.buffer.asUint8List());
client = HttpClient(context: securityContext);
return client;
};
}
Dio允许所有https
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(HttpClient client) {
client.badCertificateCallback =
(X509Certificate cert, String host, int port) {
return true;
};
};