控制WCF客户端

时间:2017-12-07 16:04:32

标签: wcf-security

自从这个问题首次在互联网上出现以来已经有好几年了,我仍然没有看到有人解决了这个问题。

WSE能够设置标志Security.EncodedMustUnderstand =“0”。 WCF似乎不再具备这种能力。自定义消息检查器永远不会在BeforeSendRequest方法中看到安全标头,并且对其中的标头所做的任何更改似乎都不会生效。

这似乎是遗留服务或Java服务的巨大互操作性问题。为什么微软还没有解决它?

有没有人为这个问题找到解决方法?

在我的所有搜索中,实际上只有一个人声称可以解决问题here。但是他们的修复程序不能在我的场景中应用,因为它根本不会修改传出消息。

我正在使用CustomBinding并需要x509证书和用户名安全性

        var security = SecurityBindingElement.CreateCertificateOverTransportBindingElement();
        //var security = new TransportSecurityBindingElement();
        security.IncludeTimestamp = true;
        security.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256;
        security.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
        //security.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11;
        //security.EndpointSupportingTokenParameters.SignedEncrypted.Add(new X509SecurityTokenParameters(X509KeyIdentifierClauseType.Any, SecurityTokenInclusionMode.AlwaysToRecipient)); // add specific x509 cert security            security.EndpointSupportingTokenParameters.Signed.Add(new UserNameSecurityTokenParameters()); // add specific username security feature
        security.EndpointSupportingTokenParameters.Signed.Add(new UserNameSecurityTokenParameters()); // add specific username security feature
        security.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
        security.EnableUnsecuredResponse = true;
        //security.ProtectTokens = false;


        //security.DefaultAlgorithmSuite = new Basic128Sha256Rsa15Sha1AlgorithmSuite(); // when we need to tweak the security suite


        var encoding = new TextMessageEncodingBindingElement();
        //encoding.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap11, AddressingVersion.None);// MessageVersion.Soap11;
        encoding.MessageVersion = MessageVersion.Soap11WSAddressingAugust2004;
        encoding.WriteEncoding = Encoding.UTF8;


        var transport = new HttpsTransportBindingElement();
        transport.MaxReceivedMessageSize = 20000000; // 20 megs
        transport.RequireClientCertificate = false;

        CustomBinding binding = new CustomBinding();
        binding.Elements.Add(security);
        binding.Elements.Add(encoding);
        //binding.Elements.Add(new TimestampedTextMsgEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
        binding.Elements.Add(transport);

编辑:

我终于能够使用自定义编码器完成这一半。微软似乎无法取消这种互操作性功能,但它可以通过自定义编码器进行攻击。

不幸的是,当服务返回看似有效的xml(在Fiddler中观察到)时,CustomEncoder在它遇到ReadMessage函数之前就会出现堆栈溢出错误。还在试图找出原因。

有时代替堆栈溢出错误,我得到了这个内部异常链:

消息:向https://service发出HTTP请求时发生错误。这可能是由于在HTTPS情况下未使用HTTP.SYS正确配置服务器证书。这也可能是由于客户端和服务器之间的安全绑定不匹配造成的。

消息:基础连接已关闭:发送时发生意外错误。

消息:无法从传输连接读取数据:远程主机强制关闭现有连接。

奇怪的是,远程主机没有强制关闭连接,远程主机似乎认为一切都成功了。所以这是.net内部的错误。要么是.net本身的问题,要么是我的自定义编码器的问题,这是直接从微软的网站复制的。

1 个答案:

答案 0 :(得分:0)

我终于能够搞清楚了。问题的根源是Microsoft从WCF中删除Security.EncodedMustUnderstand =“0”功能。无论他们选择这样做的原因是什么导致了我的大量额外工作。创建手动修改此设置的自定义编码器是我找到解决该问题的唯一方法。

当我将微软的示例代码从他们的站点复制到自定义编码器时,我的第二个大问题出现了。原来有一个隐藏的循环,它会产生堆栈溢出错误。

一旦我清理了Microsoft的示例代码,我仍然会遇到相同的HTTP.SYS错误。这次它实际上是一个有效的错误,并将代码移动到可以从https url获取调用的服务器解决了这个问题。

编辑:我写了一篇关于这个答案的详细博文here