使用Azure ACS的WCF身份验证会增加MaxReceivedMessageSize

时间:2014-02-26 09:05:26

标签: c# wcf azure acs

我有一个authenticates via Azure ACS的WCF服务,它工作得很漂亮,除了当我上传大文件时,我得到“(413)请求实体太大”

显然我需要增加MaxReceivedMessageSize,但是,我的绑定类型不是WSHttpBinding而是IssuedTokenWSTrustBinding因此不会公开此属性,我想我不会完全理解如何在下面的代码中创建HTTP绑定。是否有可能以某种方式在我的绑定上配置MaxReceivedMessageSize?

    public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
    {
        string acsUsernameEndpoint = String.Format("https://{0}.{1}/v2/wstrust/13/username", ACSServiceNamespace, AcsHostUrl);
        ServiceHost rpHost = new ServiceHost(typeof(DataTransferService));
        rpHost.Credentials.ServiceCertificate.Certificate = GetServiceCertificateWithPrivateKey();
        rpHost.AddServiceEndpoint(typeof(IUploadService),
                                   Bindings.CreateServiceBinding(acsUsernameEndpoint),
                                   new Uri(ServiceAddress));

        // Windows Identity Foundation token handlers can pick up the relevant settings.
        ServiceConfiguration serviceConfiguration = new ServiceConfiguration();
        // FederatedServiceCredentials.ConfigureServiceHost etc...
        return rpHost;
    }

    public static class Bindings
    {
        public static Binding CreateServiceBinding(string acsUsernameEndpoint)
        {
            return new IssuedTokenWSTrustBinding(CreateAcsUsernameBinding(), new EndpointAddress(acsUsernameEndpoint));
        }

        public static Binding CreateAcsUsernameBinding()
        {
            return new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential);
        }
    }

1 个答案:

答案 0 :(得分:0)

解决了!由于我没有明确定义我的端点,因此应该可以使用.Net 4+在'默认'端点上设置ReaderQuotasMaxReceivedMessageSize等通过不命名它们,这没有用。

最后,我设法通过创建一个覆盖ReaderQuotas的新Binding类来更改绑定上的MaxReceivedMessageSizeCreateBindingElements(),这个新类通过{{1并调用其IssuedTokenWSTrustBinding来创建其绑定组件的克隆,然后允许我调整设置。我留下了一个完全基于代码的WCF配置,不确定我喜欢.clone() - 可能有一个更有说服力的解决方案。

CreateBindingElements()

并按如下方式调用:

private class LargeTransportBinding : Binding
{
    Binding originalBinding;

    public LargeTransportBinding(Binding sourceBinding)
    {
        originalBinding = sourceBinding;
    }

    public override BindingElementCollection CreateBindingElements()
    {
        // Copy
        BindingElementCollection modifiedBindingElementCollection = originalBinding.CreateBindingElements().Clone();

        // Tweak Reader Quoters and max buffer sizes
        TextMessageEncodingBindingElement encoding = (TextMessageEncodingBindingElement)modifiedBindingElementCollection[1];
        encoding.ReaderQuotas.MaxArrayLength = int.MaxValue;
        encoding.ReaderQuotas.MaxBytesPerRead = int.MaxValue;
        encoding.ReaderQuotas.MaxStringContentLength = int.MaxValue;

        HttpTransportBindingElement transport = (HttpTransportBindingElement)modifiedBindingElementCollection[2];
        transport.MaxBufferPoolSize = int.MaxValue;
        transport.MaxBufferSize = int.MaxValue;
        transport.MaxReceivedMessageSize = int.MaxValue;

        return modifiedBindingElementCollection;
    }

    public override string Scheme
    {
        get { return originalBinding.Scheme; }
    }
}

记住将Int.MaxValue减少到更真实的东西,以减少DoS攻击的可能性。我希望这可以节省一些人我花在拖网上解决这个问题的日子。

对于IIS 7,web.config中也需要这样:

    var binding =  Bindings.CreateServiceBinding(acsUsernameEndpoint);
    rpHost.AddServiceEndpoint(typeof(IUploadService),
                     new LargeTransportBinding(binding),
                     new Uri(ServiceAddress));