C#消费soap WS在VerifyIncomingMessage中返回安全头错误
Posted
技术标签:
【中文标题】C#消费soap WS在VerifyIncomingMessage中返回安全头错误【英文标题】:C# consuming soap WS returns Security header error in VerifyIncomingMessage 【发布时间】:2020-09-24 20:56:11 【问题描述】:我有一个 SoapUI 项目,它的请求带有这样的soap标头中的凭据
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rgw="http://ThirdPartyWebService.wsdl">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasisopen.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasisopen.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-12346579123456789">
<wsse:Username>username</wsse:Username>
<wsse:Password>password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
.........
</soapenv:Body>
</soapenv:Envelope>
SoapUI 项目运行良好,我得到了这样的回应:
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Header/>
<env:Body>
<m:ThirdPartyWSMethodResponse xmlns:m="http://gr/gsis/ThirdPartyWS/ThirdPartyWS.wsdl">
<ThirdPartyWSBasic_out>
<m:string1>string 1</m:string1>
<m:date1 xsi:nil="true"/>
<m:string2>string 2</m:string2>
</ThirdPartyWSBasic_out>
<arrayOfThirdPartyWSFirmAct_out>
<m:ThirdPartyWSFirmActUser>
<m:Descr>some free text</m:Descr>
<m:Kind>1</m:Kind>
<m:KindDescr>some string</m:KindDescr>
<m:Code>some code as string</m:Code>
</m:ThirdPartyWSFirmActUser>
</arrayOfThirdPartyWSFirmAct_out>
<pCallSeqId_out>111111111</pCallSeqId_out>
<pErrorRec_out>
<m:errorDescr xsi:nil="true"/>
<m:errorCode xsi:nil="true"/>
</pErrorRec_out>
</m:ThirdPartyWSMethodResponse>
</env:Body>
</env:Envelope>
我正在尝试使用此代码在 C# 项目中使用相同的肥皂 WS(我将其添加为服务参考):
ThirdPartyWSClient client = new ThirdPartyWSClient();
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "password";
System.Net.ServicePointManager.ServerCertificateValidationCallback = (senderX, certificate, chain, sslPolicyErrors) => return true; ;
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
ThirdPartyWSInputUser inputBody = new ThirdPartyWSInputUser();
inputBody.parameter1 = "800542811";
ThirdPartyWSBasicUser ThirdPartyWSBasic_out = new ThirdPartyWSBasicUser();
ThirdPartyWSUserArray arrayOfThirdPartyWS_out = new ThirdPartyWSUserArray();
decimal pCallSeqId_out = new decimal();
GenWsErrorUser pErrorRec_out = new GenWsErrorUser();
client.thirdPartyWSMethod(inputBody, ref ThirdPartyWSBasic_out, ref arrayOfThirdPartyWS_out, ref pCallSeqId_out, ref pErrorRec_out);
带绑定:
<bindings>
<basicHttpBinding>
<binding name="ThirdPartyWSPublic">
<security mode="TransportWithMessageCredential" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://www.ThirdPartyWS/ThirdPartyWSPublicPort"
binding="basicHttpBinding" bindingConfiguration="RgWsPublic"
contract="SoapWebService.ThirdPartyWSPublic" name="ThirdPartyWSPublicPort" />
</client>
我收到以下错误:
安全处理器无法在邮件中找到安全标头。这可能是因为消息是不安全的错误,或者是因为通信双方之间存在绑定不匹配。如果服务配置了安全性并且客户端未使用安全性,则可能会发生这种情况。 使用此堆栈跟踪:
Server stack trace:
at System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessageCore(Message& message, TimeSpan timeout)
at System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessage(Message& message, TimeSpan timeout)
at System.ServiceModel.Security.SecurityProtocol.VerifyIncomingMessage(Message& message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at .................................
问题是无法验证传入的消息。我使用了 fiddler,发现 我得到了来自 WS 的正确响应!唯一看起来很奇怪的是,我的请求在标头中包含了一个时间戳元素,它没有 wsse: 和 soapenv: 预期的标签,但是是这样的:
<s:Envelope
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<o:Security s:mustUnderstand="1"
xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>2020-06-05T13:35:58.208Z</u:Created>
<u:Expires>2020-06-05T13:40:58.208Z</u:Expires>
</u:Timestamp>
<o:UsernameToken u:Id="uuid-11111111111111111111">
<o:Username>username</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body>
<ThirdPartyWSPublicMethod>
...
</ThirdPartyWSPublicMethod>
</s:Body>
</s:Envelope>
Web 服务是公共部门的 WS,需要身份验证,因此我无法提供。不幸的是,我无法显示确切的请求和响应,因为它们包含敏感的个人数据。 我已经尝试了我在这里和那里找到的所有东西,但无法解决这个问题。任何帮助将不胜感激!谢谢
【问题讨论】:
我认为超时是代码正在等待您不需要的代理。尝试禁用代理:***.com/questions/6579756/… 【参考方案1】:我设法通过使用自定义绑定和禁用时间戳和代理解决了这个问题。感谢@jdweng 指出正确的方向
<customBinding>
<binding name="ThirdPartyWSPublic">
<security authenticationMode="UserNameOverTransport" includeTimestamp="false">
<secureConversationBootstrap />
</security>
<textMessageEncoding messageVersion="Soap11" />
<httpsTransport useDefaultWebProxy="false" requireClientCertificate="false" />
</binding>
</customBinding>
【讨论】:
以上是关于C#消费soap WS在VerifyIncomingMessage中返回安全头错误的主要内容,如果未能解决你的问题,请参考以下文章
在 C# 中,如何使用大量精美的标记将 POCO 序列化为 XML?
从头开始使用 WS-Addressing 和 WS-Security 创建 SOAP 标头