如何通过 X509Certificate2 在 C# 中使用双向身份验证执行 SOAP API 客户端调用

How to perform SOAP API client call via X509Certificate2 with 2-way mutual authentication in C#

我接到了一个项目,涉及创建一个 SOAP API 调用 Lufthansa 的 myIdTravel API。 (在这里包括 Lufthansa 公司名称,以防任何对 Lufthansa API 有具体经验的人可以参与进来。所有 API 信息都是 public 知识,我已经混淆了任何私人信息,比如“密码”。)

虽然我有很多使用 OAuth2 的 ReST API 经验,但我完全没有 SOAP 经验,而且我发现这种体验非常令人沮丧。

汉莎航空向我提供了一个 client.pfx 文件和以下 示例 SOAP XML 正文:

<soapenv:Envelope   xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                    xmlns:ser="http://service.login.myidtravel.com" 
                    xmlns:bos="http://bos.login.myidtravel.com" 
                    xmlns:ser1="http://service.wsgateway-v2.myidtravel.lhsystems.com">
   <soapenv:Header/>
   <soapenv:Body>
      <ser:StaffProfilesUploadRequest ac="YY">
         <ser:updateRecord>
            <ser:employee ptc="ZEA" lastname="Test" firstname="emp" middlename="midd" salutation="MR" title="Dr." gender="M" laborGroup="pilot" dob="1990-01-01">
               <bos:employment eID="uploadTest" doj="2000-01-01" />
               <bos:accounting costCenter="123" />
               <bos:contact emailAddress="abc@myidtravel.com" phone1="1234" phone2="23456" mobileNumber="545454"/>
               <bos:entitled-person ptc="ZSP" lastname="test" firstname="entit" middlename="spouse" salutation="MR" dob="1995-01-01" externalPersonID="2" />
               <bos:employment-status startDate="2000-01-01" status="retired"/>
         </ser:employee>
         </ser:updateRecord>
      </ser:StaffProfilesUploadRequest>
   </soapenv:Body>
</soapenv:Envelope>

通过反复试验,我得出了以下 C# 代码,它至少联系了 API,但返回了 "500 internal server error"。它还使用根据我的特定需求量身定制的 XML。

HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://integration.myidtravel.com/services/Gateway_V2");

request.Method = "POST";
request.ContentType = "text/xml;charset=\"utf-8\"";
request.Accept = "text/xml, application/xhtml+xml, */*";

var cert = new X509Certificate2(@"C:\client.pfx", "password");

request.ClientCertificates.Add(cert);

XmlDocument xml = new XmlDocument();

xml.LoadXml(
    @"<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:ser='http://service.login.myidtravel.com' xmlns:bos='http://bos.login.myidtravel.com'>
        <soapenv:Header>
        </soapenv:Header>
        <soapenv:Body>
            <ser:StaffProfilesUploadRequest ac='XX'>
                <ser:updateRecord>
                    <ser:employee ptc='ZEA' lastname='Wallace' firstname='Kirby' middlename='L.' dob='1999-01-01'>
                        <bos:employment eID='123456'/>
                    </ser:employee>
                </ser:updateRecord>
            </ser:StaffProfilesUploadRequest>
        </soapenv:Body>
    </soapenv:Envelope>"
);

using (Stream stream = request.GetRequestStream()) {
    xml.Save(stream);
}

using (StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream())) { // <--- ERROR HERE
    string response = reader.ReadToEnd();
}

request.GetReponse() 上引发错误时,cert 已加载并且似乎是有效的 X509 证书。 cert.Thumbprint, cert.PrivateKeycert.PublicKeycert.NotBeforecert.NotAfter(以及所有其他属性)似乎都包含有效值。

但是 API 在 .GetResponse() 后返回 500 Internal Server Error

我缺少哪些步骤,或者我还需要做什么?我在这里停滞不前,因为我没有足够的 SOAP 经验来知道我做错了什么。任何帮助表示赞赏。

如果我的异常情况对其他人有帮助,让我解释一下是什么原因造成的。我不知道修复它所需的步骤,但我知道是什么原因造成的并解决了它。

通过查看响应 headers 和 SoapUI 提供的证书,我发现我的公司在网络上做了一些事情,剥离了我的 SSL 证书,并替换了他们自己的 SSL 证书。因此,我的请求到达远程 API 减去它应该为相互身份验证握手提供的 SSL。

希望对以后的其他人有所帮助。特别是如果您在公司防火墙后面工作。