You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 23:27:06