Rust中使用PFX证书调用Web API返回401问题求助
调用需证书验证的Web API时Rust代码返回401错误(Postman和C#可正常执行)
我需要调用一个要求证书与密钥验证的Web API,在Postman中安装.pfx证书后可以正常调用,但用Rust代码调用时始终返回401错误。核心问题是如何在Rust的API客户端中正确配置有效证书。
解密后的密钥格式
Bag Attributes localKeyID: 01 00 00 00 friendlyName: te-XXXXXXX-3fab-4XXX3-8505-1c7XXXXXXXXXXbb Microsoft CSP Name: Microsoft Software Key Storage Provider Key Attributes X509v3 Key Usage: 90 -----BEGIN PRIVATE KEY----- // key withheld -----END PRIVATE KEY----- Bag Attributes localKeyID: 01 00 00 00 1.3.6.1.4.1.311.17.3.71: 45 00 43 00 //etc subject=CN = companyCert issuer=CN = companyCert -----BEGIN CERTIFICATE----- // cert withheld -----END CERTIFICATE-----
尝试的Rust代码及执行结果
我试过直接读取PFX文件、转换为PEM文件两种方式,也分别用rustls和native_tls库适配,都没解决问题。目前最接近可行的代码如下:
use native_tls::TlsConnector; use openssl::pkcs12::Pkcs12; use openssl::ssl::{SslConnector, SslMethod}; use reqwest::Client; use std::fs::File; use std::io::Read; use tokio; async fn call_api() -> Result<(), Box<dyn std::error::Error>> { let mut buf = vec![]; File::open("cer.pfx")?.read_to_end(&mut buf)?; let pkcs12 = Pkcs12::from_der(&buf)?.parse("password")?; let mut ssl_builder = SslConnector::builder(SslMethod::tls())?; ssl_builder.set_certificate(&pkcs12.cert)?; ssl_builder.set_private_key(&pkcs12.pkey)?; let tls_connector = TlsConnector::builder() .danger_accept_invalid_certs(true) .danger_accept_invalid_hostnames(true) .build()?; let client = reqwest::Client::builder() .use_preconfigured_tls(tls_connector) .build()?; let mut headers = reqwest::header::HeaderMap::new(); headers.insert("Content-Type", "application/json".parse()?); headers.insert( "Authorization", "GGL-API-KEY XXXX-XXXX-XXXX-XXXX-XXXX".parse()?, ); let request = client.request(reqwest::Method::GET, "https://example.api") .headers(headers); println!("request: {:?}", request); let response = request.send().await?; println!("response: {:?}", response); let body = response.text().await?; println!("{}", body); Ok(()) } #[tokio::main] async fn main() { match call_api().await { Err(e) => eprintln!("Error: {}", e), _ => (), } }
执行后返回结果:
request: RequestBuilder { method: GET, url: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("example.api")), port: None, path: "/api/cardholders", query: Some("fields=example"), fragment: None }, headers: {"content-type": "application/json", "authorization": "GGL-API-KEY XXXX-XXXX-XXXX-XXXX"} } response: Response { url: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("example.api")), port: None, path: "/api/XXXXX", query: Some("fields=example"), fragment: None }, status: 401, headers: {"content-length": "0", "date": "Mon, 19 Feb 2024 04:09:01 GMT"} }
可行的C#代码
使用相同证书的C#代码可以成功调用该API:
X509Certificate2 apiCertificate = new X509Certificate2(path, config["CertificatePassword"]); handler.ClientCertificateOptions = ClientCertificateOption.Manual; handler.ClientCertificates.Add(apiCertificate); HttpClient httpClient = new HttpClient(handler); httpClient.DefaultRequestHeaders.Add("Authorization", config["ApiKey"]); httpClient.DefaultRequestHeaders.Add("Accept", "application/json"); var myResponse = await httpClient.GetAsync(config["URL"]);
恳请协助解决Rust代码中证书配置导致的401问题。
内容的提问来源于stack exchange,提问作者Myles Pritchett
相关产品推荐
相关产品推荐

