我正在努力使用WCF
绑定配置。我已添加第三方服务作为我的项目的参考。我收到了一些规格。
我需要使用SOAP v1.2
所以我认为我需要WSHttpBinding
它将是https
所以我需要SecurityMode.Transport
这样的事情:
var binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Transport;
var client = new MyClient(binding, addr);
var result = client.Method(new MyObject());
导致此请求正文。
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
<S:Header>
<wsa:MessageID>
uuid:6B29FC40-CA47-1067-B31D-00DD010662DA
</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>example</wsa:Address>
</wsa:ReplyTo>
<wsa:To>example</wsa:To>
<wsa:Action>example</wsa:Action>
</S:Header>
<S:Body>
<MyObject>...</MyObject>
</S:Body>
</S:Envelope>
根据我提供的规范,我需要在Security
和UsernameToken
的标题中包含Timestamp
元素。正是我对BasicHttpBinding
和BasicHttpSecurityMode.TransportWithMessageCredential
当我尝试将TransportWithMessageCredential
模式设置为WSHttpBinding
请求正文发生剧烈变化时。
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
var client = new MyClient(binding, addr);
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "123456";
var result = client.Method(new MyObject());
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
<S:Header>
<wsa:MessageID>
uuid:b633067e-9a9e-4216-b036-4afa3aca161e
</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:To>example</wsa:To>
<wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT</wsa:Action>
<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:Timestamp>
<o:UsernameToken>
<o:Username>...</o:Username>
<o:Password>...</o:Password>
</o:UsernameToken>
</o:Security>
</S:Header>
<S:Body>
<t:RequestSecurityToken>...</t:RequestSecurityToken>
</S:Body>
</S:Envelope>
现在我的安全部分是正确的,但所有寻址部分都是错误的,身体也是如此。我该怎么办?
我期待(我需要)这样的事情:
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
<S:Header>
<wsa:MessageID>
uuid:6B29FC40-CA47-1067-B31D-00DD010662DA
</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>example</wsa:Address>
</wsa:ReplyTo>
<wsa:To>example</wsa:To>
<wsa:Action>example</wsa:Action>
<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:Timestamp>
<o:UsernameToken>
<o:Username>...</o:Username>
<o:Password>...</o:Password>
</o:UsernameToken>
</o:Security>
</S:Header>
<S:Body>
<MyObject>...</MyObject>
</S:Body>
</S:Envelope>
答案 0 :(得分:0)
您发布的第二个数据包不是WCF呼叫请求,而是安全通道设置的一部分。这是RequestSecurityToken
数据包,将以RequestSecurityTokenResponse
回答。之后,如果频道设置正确,则会在您在第一个片段中发布时发送带有方法调用的相同数据包。您可以在Service Trace Viewer中看到此数据包序列:
您尝试解决的实际问题是什么?您的WCF呼叫失败了吗?如果是这样,请提供例外细节。最可能的原因是WCF配置或身份验证错误。
如果您努力避免这些协商数据包,请查看此answer,其中显示如何将SecurityMode
切换为Message
并将NegotiateServiceCredential
选项设置为false
。
<强>更新强>
这部分与问题更新有关,要求修复请求的部分寻址。
要手动设置wsa:ReplyTo标头,您需要设置ReplyTo的OperationContext.OutgoingMessageHeaders属性,如下所示:
using (new OperationContextScope(client.InnerChannel))
{
OperationContext.Current.OutgoingMessageHeaders.ReplyTo = new EndpointAddress("http://someclient/callback");
var request = client.Method(new MyObject());
}
有关详细信息,请参阅此answer。
答案 1 :(得分:0)
最后,我不得不使用CustomBinding
发送所需的请求。
var b = new CustomBinding();
var security = TransportSecurityBindingElement.CreateUserNameOverTransportBindingElement();
security.IncludeTimestamp = true;
security.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Default;
security.MessageSecurityVersion = MessageSecurityVersion.Default;
security.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
security.EnableUnsecuredResponse = true;
var encoding = new TextMessageEncodingBindingElement();
encoding.MessageVersion = MessageVersion.Soap12WSAddressing10;
var transport = new HttpsTransportBindingElement
{
MaxBufferPoolSize = 2147483647,
MaxBufferSize = 2147483647,
MaxReceivedMessageSize = 2147483647,
};
b.Elements.Add(security);
b.Elements.Add(encoding);
b.Elements.Add(transport);
var client = new MyClient(binding, addr);
var result = client.Method(new MyObject());