【发布时间】:2018-07-09 22:34:25
【问题描述】:
与我合作的一家公司提供 SOAP API 来自动使用他们的服务。
API 文档说“API 几乎是通用的 可接受:SOAP 客户端可用于 PHP、PERL、Python 和 Java。 但是,客户在集成到 C# 时遇到了挑战 环境”
当我从 SoapUI 进行 SOAP 调用时,我可以成功地使用 API 进行身份验证。但是,当我在 Visual Studio 中将 WSDL 文件链接为 C# 中的服务引用时,我从 API 获得响应,但身份验证总是失败。
认证操作需要3个参数:
<part name="salt" type="xsd:string"/>
<part name="token" type="xsd:string"/>
<part name="budgetID" type="xsd:string"/>
salt 是随机字母或数字,token 是 salt 和我的密码的哈希值,budgetID 是我帐户的唯一标识符。
SoapUI 进行以下调用并得到我想要的确切结果:
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn="urn:loginService">
<soapenv:Header/>
<soapenv:Body>
<urn:doLogin soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<salt xsi:type="xsd:string">12</salt>
<token xsi:type="xsd:string">ae4894ac690d70b0a3ebf27763</token>
<budgetID xsi:type="xsd:string">6e080f339657ce5be68059bec9</budgetID>
</urn:doLogin>
</soapenv:Body>
</soapenv:Envelope>
但是,当我使用链接的服务参考在 C# 中进行类似调用时,使用如下代码,我从 API 获得响应,但它无法进行身份验证:
Random rnd = new Random();
int salt = rnd.Next(1, 10000);
string token;
string budgetKey = "XXX";
using(MD5 md5Hash = MD5.Create())
{
token GetMD5Hash(md5Hash, (salt + txtBudgetPassword.Password).ToString());
}
//Instantiate the web services client created by my Service Reference
loginServicePortClient login = new loginServicePortClient();
Console.Write(login.doLogin(salt, token.ToString(), budgetKey));
.NET/C# SOAP 客户端是否存在一些已知问题,使完全相同的凭据无法在此客户端中工作?我知道这不是 MD5 哈希的问题,因为该函数的输出是我用来在 SoapUI 中成功测试调用的输出。
我很难相信在 C#/.NET 中无法使用此 API。
API 文档在here 可用。
编辑:以下是来自 SoapUI 和 C# 调用的标头:
SoapUI:
POST /Budget/loginService.php HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: "urn:loginService#loginService#doLogin"
Content-Length: 609
Host: api.textbroker.com
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
C#:
CONNECT api.textbroker.com:443 HTTP/1.1
Host: api.textbroker.com
Connection: Keep-Alive
【问题讨论】:
-
调试此类问题的最佳方法是使用像wireshark 或fiddler 这样的嗅探器。使用 SoapUi 捕获良好的结果并与 c# 结果进行比较。查看http headers并比较好坏,通常可以通过在c#代码中添加缺少的headers来解决问题。
-
我已将两个请求的原始标头添加到原始帖子中。有什么东西会从 C# 中跳出来吗?我对这些东西不是很熟悉,也不知道如何编辑 C# 请求中的标头。
-
However, when I make a similar call in C# using the linked Service Reference, using code like below:感觉好像我们漏掉了那句话的结尾。 -
所有差异都很重要。 http 的第一个标准端口号是 80(或 8080)。您使用的是 443,即 https(安全)。然后您使用的是 http 1.1(块模式),它不适用于 httprequest。通常我必须强制 httprequest 使用 1.0(流模式)。块模式需要发送下一个块消息,我还没有找到发送下一个块的方法。然后在c#中你需要处理gzip模式。最后,Content-Type 是错误的。
-
@jdweng 所以 API 提供的 WSDL 地址是一个 HTTPS 地址。我还应该尝试通过 HTTP 执行此操作吗?