C# WSHttpBinding TransportWithMessageCredential安全模式更改请求

C# WSHttpBinding TransportWithMessageCredential安全模式更改请求,c#,web-services,wcf,soap,ws-security,C#,Web Services,Wcf,Soap,Ws Security,我正在努力进行WCF绑定配置。我已经添加了第三方服务作为我项目的参考。我得到了一些规格说明 我需要使用SOAPV1.2所以我想我需要WSHttpBinding它将是https所以我需要SecurityMode.Transport 大概是这样的: var binding = new WSHttpBinding(); binding.Security.Mode = SecurityMode.Transport; var client = new MyClient(binding, addr); va

我正在努力进行
WCF
绑定配置。我已经添加了第三方服务作为我项目的参考。我得到了一些规格说明

我需要使用
SOAPV1.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());
using (new OperationContextScope(client.InnerChannel))
{
    OperationContext.Current.OutgoingMessageHeaders.ReplyTo = new EndpointAddress("http://someclient/callback");
    var request = client.Method(new MyObject());
}
它产生了这个请求体


uuid:6B29FC40-CA47-1067-B31D-00DD010662DA
例子
例子
例子
...
根据提供给我的规范,我需要在带有
UsernameToken
Timestamp
的标题中包含
Security
元素。与
BasicHttpBinding
BasicHttpSecurityMode.TransportWithMessageCredential

当我尝试用
WSHttpBinding
设置
TransportWithMessageCredential
模式时,请求正文会发生剧烈变化

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());

uuid:b633067e-9a9e-4216-b036-4afa3aca161e
http://www.w3.org/2005/08/addressing/anonymous
例子
http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT
...
...
...
...
现在我的安全部分是正确的,但是所有的寻址部分都是错误的,主体也是错误的。我该怎么办

我期待(而且我需要)像这样的事情:

var binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Transport;
var client = new MyClient(binding, addr);
var result = client.Method(new MyObject());
using (new OperationContextScope(client.InnerChannel))
{
    OperationContext.Current.OutgoingMessageHeaders.ReplyTo = new EndpointAddress("http://someclient/callback");
    var request = client.Method(new MyObject());
}

uuid:6B29FC40-CA47-1067-B31D-00DD010662DA
例子
例子
例子
...
...
...
...

您发布的第二个数据包不是WCF呼叫请求,而是安全通道设置的一部分。这是
RequestSecurityToken
数据包,将使用
RequestSecurityTokenResponse
进行应答。之后,如果通道设置正确,将发送与您在第一个代码段中发布的相同的带有方法调用的数据包。您可以在服务跟踪查看器中看到此数据包序列:

您试图解决的实际问题是什么?你的WCF呼叫失败了吗?如果是,请提供例外情况的详细信息。最可能的原因是WCF配置或身份验证错误

如果您试图避免这些协商数据包,请选中此项,以显示如何将
SecurityMode
切换到
Message
,并将
NegotiateServiceCredential
选项设置为
false

更新:

此部分与问题更新相关,该问题更新要求修复请求的寻址部分

要手动设置wsa:ReplyTo标头,需要设置的属性,如下所示:

var binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Transport;
var client = new MyClient(binding, addr);
var result = client.Method(new MyObject());
using (new OperationContextScope(client.InnerChannel))
{
    OperationContext.Current.OutgoingMessageHeaders.ReplyTo = new EndpointAddress("http://someclient/callback");
    var request = client.Method(new MyObject());
}

更多详情请参见此。

最后,我不得不使用
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());

我建议你尝试下面的步骤来回答问题。我更新了问题并提供了我需要的请求主体。