WCF - 如何使用 HTTP(S) 上的二进制编码以编程方式创建自定义绑定

Posted

技术标签:

【中文标题】WCF - 如何使用 HTTP(S) 上的二进制编码以编程方式创建自定义绑定【英文标题】:WCF - how to create programatically custom binding with binary encoding over HTTP(S) 【发布时间】:2011-01-15 05:00:56 【问题描述】:

我想将我当前的 HTTP/HTTPS WCF 绑定设置转换为使用二进制消息编码,我需要在代码中进行,而不是在 XML 配置中。 AFAIK 有必要创建 CustomBinding 对象并设置正确的 BindingElements,但我无法弄清楚在我的场景中应该使用哪些元素。

我的 WCF 配置中的要点是:

根据配置使用 HTTP 或 HTTPS 传输(在 app.config 中) 使用用户名消息安全 todo:添加二进制编码而不是默认文本

我当前设置绑定的代码(工作,但没有二进制编码):

var isHttps = Settings.Default.wcfServiceBaseAddress.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase);
var binding = new WSHttpBinding(isHttps ? SecurityMode.TransportWithMessageCredential : SecurityMode.Message);
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

我正在尝试此代码,但它不起作用 - 我不知道如何为用户名消息安全设置消息安全元素:

var custBinding = new CustomBinding();
custBinding.Elements.Add(new BinaryMessageEncodingBindingElement());
//Transport Security (Not Required)
if (isHttps)

    custBinding.Elements.Add(SecurityBindingElement.CreateUserNameForSslBindingElement());

//Transport (Required)
custBinding.Elements.Add(isHttps ?
    new HttpsTransportBindingElement() :
    new HttpTransportBindingElement());

有人知道怎么设置吗?我试图搜索类似的问题/解决方案,但没有成功...

【问题讨论】:

【参考方案1】:

我差点忘了这个问题,但这是我的自定义绑定类,它通过 HTTP 与用户名+密码验证进行二进制绑定,还允许打开 GZip 压缩...

    public class CustomHttpBinding: CustomBinding

    private readonly bool useHttps;
    private readonly bool useBinaryEncoding;
    private readonly bool useCompression;
    private readonly HttpTransportBindingElement transport;

    public CustomHttpBinding(bool useHttps, bool binaryEncoding = true, bool compressMessages = false)
    
        this.useHttps = useHttps;
        transport = useHttps ? new HttpsTransportBindingElement() : new HttpTransportBindingElement();
        useBinaryEncoding = binaryEncoding;
        useCompression = compressMessages;
    

    public long MaxMessageSizeset
    
        transport.MaxReceivedMessageSize = value;
        transport.MaxBufferSize = (int) value;
    

    public override BindingElementCollection CreateBindingElements()
    
        BindingElement security;
        if (useHttps)
        
            security = SecurityBindingElement.CreateSecureConversationBindingElement(
                SecurityBindingElement.CreateUserNameOverTransportBindingElement());
        
        else
        
            security = SecurityBindingElement.CreateSecureConversationBindingElement(
                SecurityBindingElement.CreateUserNameForSslBindingElement(true));
        

        MessageEncodingBindingElement encoding;
        if (useCompression)
        
            encoding = new GZipMessageEncodingBindingElement(useBinaryEncoding
                                                                ? (MessageEncodingBindingElement)
                                                                  new BinaryMessageEncodingBindingElement()
                                                                : new TextMessageEncodingBindingElement());
        
        else
        
            encoding = useBinaryEncoding
                        ? (MessageEncodingBindingElement) new BinaryMessageEncodingBindingElement()
                        : new TextMessageEncodingBindingElement();
        

        return new BindingElementCollection(new[]
            
                security,
                encoding,
                transport,
            );
    

【讨论】:

【参考方案2】:

SecurityBindingElement 具有 AllowInsecureTransport 属性。如果将此设置为 true,则可以使用具有消息用户名和密码安全性的 HttpTransportBindingElement。

【讨论】:

【参考方案3】:

改用SecurityBindingElement.CreateUserNameOverTransportBindingElement()

var custBinding = new CustomBinding();
custBinding.Elements.Add(new BinaryMessageEncodingBindingElement());
//Transport Security (Not Required)
if (isHttps)

  custBinding.Elements.Add(SecurityBindingElement.CreateUserNameOverTransportBindingElement());

//Transport (Required)
custBinding.Elements.Add(isHttps ?
   new HttpsTransportBindingElement() :
   new HttpTransportBindingElement());

【讨论】:

我已经尝试过了,但它不起作用。此外,当 isHttps==false 没有消息安全设置时 - 这是主要问题。我不知道如何使用 CustomBinding 设置与 WSHttpBinding 兼容的消息安全性。 出于安全原因,WCF 仅允许在加密连接时发送用户名/密码组合 - 即当您使用 Https 传输时。这意味着如果您不使用 Https,则无法以这种方式保护您的消息。您可能需要重新评估您的要求。

以上是关于WCF - 如何使用 HTTP(S) 上的二进制编码以编程方式创建自定义绑定的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在同一端口上的 HTTP 中创建另一个端点?

WCF 服务上的多个绑定

WCF:自托管服务上的 HTTP 400 错误请求

Monotouch/WCF:如何在没有 svcutil 的情况下使用 wcf 服务

C#如何编译为二进制可执行文件?

WCF 服务的 basicHttpBinding 上的 HTTPS