如何解决Rust Reqwest无效证书错误:自签名证书未被识别
解决Reqwest客户端访问自签名TLS服务器时的CertificateUnknown错误
可能的原因及解决方案
1. 服务器证书缺少访问IP的SAN字段
Reqwest默认使用的rustls后端对证书的**Subject Alternative Name(SAN)**验证严格,若你通过IP地址访问服务器,但证书未将该IP添加到SAN字段,就会触发验证失败,服务器端返回CertificateUnknown错误。
验证方法:
用OpenSSL命令查看证书内容:
openssl x509 -in my_cert.pem -text -noout
找到X509v3 Subject Alternative Name字段,确认是否包含你访问用的IP(格式如IP:xxx.xxx.xxx.xxx)。
解决方法:
重新生成自签名证书,添加IP作为SAN字段。示例OpenSSL命令:
openssl req -x509 -newkey rsa:4096 -keyout my_key.pem -out my_cert.pem -days 365 -nodes \ -subj "/CN=localhost" \ -addext "subjectAltName=IP:192.168.1.100" # 替换为你的服务器IP
2. 确认添加的证书格式正确
确保添加到Reqwest客户端的是服务器使用的自签名证书本身(而非私钥或其他证书),且PEM文件仅包含证书内容(无私钥)。
检查PEM文件内容,应类似:
-----BEGIN CERTIFICATE----- ... 证书内容 ... -----END CERTIFICATE-----
若文件中包含-----BEGIN PRIVATE KEY-----开头的内容,请删除私钥部分,仅保留证书部分。
3. 临时禁用主机名验证(仅测试环境)
如果是测试环境,可临时禁用Reqwest的主机名验证,快速确认问题是否源于SAN字段缺失:
let mut buf = Vec::new(); File::open("my_cert.pem")? .read_to_end(&mut buf)?; let cert = reqwest::Certificate::from_pem(&buf)?; let client = reqwest::Client::builder() .add_root_certificate(cert) .danger_accept_invalid_hostnames(true) // 仅测试用,生产环境禁止使用 .build()?; let mut map = HashMap::new(); map.insert("name", "John"); let res = client.post("https://IP:PORT/endpoint").json(&map).send().await?;
4. 切换到native-tls后端
Reqwest默认使用rustls,切换到依赖系统TLS库的native-tls后端可能解决兼容性问题:
- 修改
Cargo.toml中的reqwest依赖:
reqwest = { version = "0.11", features = ["native-tls", "json"] }
- 保持原有代码不变,重新编译运行。
内容的提问来源于stack exchange,提问作者Haider Khan
相关产品推荐
相关产品推荐

