如何通过 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.PrivateKey
、cert.PublicKey
、cert.NotBefore
和 cert.NotAfter
(以及所有其他属性)似乎都包含有效值。
但是 API 在 .GetResponse()
后返回 500 Internal Server Error
。
我缺少哪些步骤,或者我还需要做什么?我在这里停滞不前,因为我没有足够的 SOAP 经验来知道我做错了什么。任何帮助表示赞赏。
如果我的异常情况对其他人有帮助,让我解释一下是什么原因造成的。我不知道修复它所需的步骤,但我知道是什么原因造成的并解决了它。
通过查看响应 headers 和 SoapUI 提供的证书,我发现我的公司在网络上做了一些事情,剥离了我的 SSL 证书,并替换了他们自己的 SSL 证书。因此,我的请求到达远程 API 减去它应该为相互身份验证握手提供的 SSL。
希望对以后的其他人有所帮助。特别是如果您在公司防火墙后面工作。
我接到了一个项目,涉及创建一个 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.PrivateKey
、cert.PublicKey
、cert.NotBefore
和 cert.NotAfter
(以及所有其他属性)似乎都包含有效值。
但是 API 在 .GetResponse()
后返回 500 Internal Server Error
。
我缺少哪些步骤,或者我还需要做什么?我在这里停滞不前,因为我没有足够的 SOAP 经验来知道我做错了什么。任何帮助表示赞赏。
如果我的异常情况对其他人有帮助,让我解释一下是什么原因造成的。我不知道修复它所需的步骤,但我知道是什么原因造成的并解决了它。
通过查看响应 headers 和 SoapUI 提供的证书,我发现我的公司在网络上做了一些事情,剥离了我的 SSL 证书,并替换了他们自己的 SSL 证书。因此,我的请求到达远程 API 减去它应该为相互身份验证握手提供的 SSL。
希望对以后的其他人有所帮助。特别是如果您在公司防火墙后面工作。