WCF: Multiple Secure Ports

By AdamJune 25, 2012 at 5:09 AM

The Problem

We were faced with an interesting issue on a project recently.  We had WCF (Windows Communication Framework) running on a custom port (as IIS does not allow more than one HTTPS site per port, per IP) and once we purchased a second IP address, we moved the web services site to the regular HTTPS port (443) on that new URL.  But because we already had clients in the field running the application that called the web services, we needed to maintain both ports on the same DNS name (443 and the custom port).   The problem?  WCF does not support this scenario without modification, especially if you have a custom ServiceHost (which we do as we wanted to introduce StructureMap into the WCF bootstrap process).  Let’s look at the solution.

The Solution

The first step in the solution is to tell WCF that you actually want to support this scenario.  You simply add the following line (line #2) to your web.config file in your WCF web services web site:

<system.serviceModel>
		<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
		<bindings>
			<basicHttpBinding>
				<binding name="BasicHttpBinding_INotify" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferSize="524288" maxBufferPoolSize="524288" maxReceivedMessageSize="524288"
                    messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                    useDefaultWebProxy="true">
					<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
					<security mode="TransportWithMessageCredential">
						<transport clientCredentialType="None" proxyCredentialType="None"
                            realm="" />
						<message clientCredentialType="UserName" algorithmSuite="Default" />
					</security>
				</binding>
			</basicHttpBinding>
		</bindings>
</system.serviceModel>

 

The next step is to make sure that all your end points are using relative Uri’s and not absolute.  In our custom ServiceHostwe had the following code (note line #27):

public ServicesServiceHost(Type serviceType, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
            serviceBehaviourType = typeof(ServicesServiceBehavior<>).MakeGenericType(serviceType);
            Initialize(serviceType, baseAddresses);
        }

protected void Initialize(Type serviceType, params Uri[] baseAddresses)
        {
            var httpsAddresses = from ba in baseAddresses
                                 where ba.Scheme == Uri.UriSchemeHttps
                                 select ba;

            ConfigureAuthentication();

            foreach (var httpsAddress in httpsAddresses)
            {
                var serviceContract = serviceType.GetInterfaceWithAttribute(typeof(ServiceContractAttribute));
                if (serviceContract == null)
                {
                    serviceContract = serviceType;
                }

                var binding = ConfigureBinding();
                try
                {
                    this.AddServiceEndpoint(serviceContract, binding, httpsAddress);
                }
                catch (Exception e)
                {
                }

                if (!this.Description.Behaviors.Contains(typeof(ServiceMetadataBehavior)))
                {
                    this.Description.Behaviors.Add(new ServiceMetadataBehavior()
                    {
                        HttpGetEnabled = true
                    });
                }
                var mex = MetadataExchangeBindings.CreateMexHttpBinding();
                this.AddServiceEndpoint(typeof(IMetadataExchange), mex, "mex");

                ((ServiceDebugBehavior)this.Description.Behaviors[typeof(ServiceDebugBehavior)])
	.IncludeExceptionDetailInFaults = true;
                ServiceSecurityAuditBehavior ssab = new ServiceSecurityAuditBehavior()
                {
                    AuditLogLocation = AuditLogLocation.Application,
                    MessageAuthenticationAuditLevel = AuditLevel.SuccessOrFailure,
                    ServiceAuthorizationAuditLevel = AuditLevel.SuccessOrFailure,
                    SuppressAuditFailure = false
                };
                this.Description.Behaviors.Add(ssab);
            }
        }

The simple solution was to change line #27 to:

this.AddServiceEndpoint(serviceContract, binding, "");

and everything worked.  To achieve the same results in XML, you simply would add an endpoint description to the XML like this (note that the address attributes are empty):

<service 
    name="Microsoft.ServiceModel.Samples.CalculatorService"
    behaviorConfiguration="CalculatorServiceBehavior">
  <!-- This endpoint is exposed at the base address provided by host: http://localhost/servicemodelsamples/service.svc  -->
  <endpoint address=""
            binding="basicHttpBinding"
            contract="Microsoft.ServiceModel.Samples.ICalculator" />
  <!-- secure endpoint exposed at {base address}/secure: http://localhost/servicemodelsamples/service.svc/secure -->
  <endpoint address="secure"
            binding="wsHttpBinding"
            contract="Microsoft.ServiceModel.Samples.ICalculator" />
  ...
</service>

Posted in: Programming

Tags:



Welcome to the team, Marc Robichaud

By Sebastien AubeMay 23, 2012 at 11:39 AM

We are happy to announce that Marc Robichaud has joined our growing company. Marc will take on the role of Business Development and client relations. 

Marc Robichaud brings over 15 years of experience in the field of information technology as a software developer and IT consulting.

Prior to joining Cognitive X Solutions, Marc has worked as an IT consultant in various federal and provincial departments including DND, CIC, Measurement Canada, Security Intelligence Review Committee and Public Service Staff Relations Board.

Through his global software development and system integration experience, his continuing objective is to provide quality IT consulting advice and services to Cognitive X Solutions’ clients.

Marc is a graduate from the Universite de Moncton and has attended various training and development courses throughout the years.

He also is an executive board member of the Dieppe Youth House Inc., president of the Dieppe Skating Club Inc., as well as a board member of Skate Canada New Brunswick Section.

Marc offers his IT knowledge to many non-profit organisms and enjoys volunteering by coaching soccer.

Marc has two children and lives in Dieppe.

 

Here's how to reach Marc

Phone: 506.800.1140

Toll Free: 1.800.670.2649(COGX) ext 106

Email: marc@cognitivex.com 

 

About Cognitive X Solutions


Cognitive X Solutions Inc., founded in 2006, is headquartered in Moncton New Brunswick with 4 full time employees.

Cognitive X Solutions Inc. is involved in various facets of information technology and business solutions development.  Our services include custom application development including web, mobile and desktop development. Our experienced staff has the ability to solve most IT problems in an intelligent and effective manner.

Cognitive X Solutions possesses the ability to create maximum efficiency processes and technology for our clients.  We believe in exceeding expectations by delivering consistent, repeatable performance.

 

Our Mission

We want to help our customers grow their business by solving problems with an Innovative application of Information Technology. We are a team of passionate software craftsmen that believe the true power of technology is the people that enables it.

 

Posted in: Growth

Tags: