WCF service hosted on IIS runs over http behind load balanced servers. The load balancer is configured to perform ssl offloading.
The WCF service is perfectly browsed on the server box over http. The same service is also browsed properly without any issues at the client side. When we consume the wsdl and hit the service request using any tool, there was no response from the service.
Client(https) --->>>> LoadBalancer ---->>>> Service(http)
The only issue is with metadata. When we take a peek at the address in the SOAP:Address, it still used to point to http address for the https wsdl.
And, its wsdl looks like the following:
<wsdl:port name="BasicHttpBinding_ITestService" binding="tns:BasicHttpBinding_ITestService">
<soap:address location="http://www.myserver.com/Service/TestService.svc" />
This means though the client tries to access the service over https, it still gets redirected to http because of soap:address location.
Use the following cusotmBinding in service web.config:
<readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647" />
<security allowInsecureTransport="true" enableUnsecuredResponse="true">
<secureConversationBootstrap requireDerivedKeys="false" />
<httpTransport maxReceivedMessageSize ="2147483647" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" />
If enableUnsecuredResponse value set to true, the following new features are enabled in WCF:
- WCF clients can accept unsecured responses even if the outgoing messages are secured by using the Secure Socket Layer (SSL) protocol to sign the message body.
- WCF services can send unsecured responses that have no security header in SOAP envelopes even if the request is secured.
If allowInsecureTransport value set to true, Mixed-Mode security binding with http as the transport is allowed instead of the secure https option.
If requireDerivedKeys value set to false, it will specify the keys won’t be derived from the original proof keys.
Other values are just set to the highest values, because we had to accommodate large data transfer too.
In order to test on the client,
- Take a console application
- Add service reference
- Modify app.config binding to use the same customBinding as of service web.config
- The test will be successful
Another alternative is to modify the wsdl completely, and make it available over https on the service side.
This involves modifying the wsdl location to point to a virtual directory and state explicitly that metadataLocation is modified to the virtual directory instead of the actual schema.
How can we make it?
Create a folder named Metadata.
Download metadata by visual studio command prompt:
>svcutil /t:metadata https://www.myserver.com/Service/TestService.svc?wsdl
It will download a list of xsd and wsdl files.
Let us target wsdl files first and then the xsd files in order to modify namespace and schmeLocation to point out to https.
- Modify xmlns:tns and targetNamespace to https://www.myserver.com/Service inside <wsdl:definitions>
- Modify targetNamespace to https://www.myserver.com/Service/Imports inside <wsdl:types> <xsd:schema>
- Modify schemaLocation to https://www.myserver.com/Service/XsdFile1.xsd and namespace to https://www.myserver.com/Service inside <wsdl:types> <xsd:schema> <xsd:import>. Follow the similar steps for the rest of imports
- Modify namespace reference to https inside <wsdl:message> <wsdl:part>
- Modify action to https inside <wsdl:portType> <wsdl:operation> for <wsdl:input> and <wsdl:output>
- Identify custom namespaces, modify namespace links to https. Ensure xmls:tns and targetNamespace values are same (we need not modify this)
- Modify wsdl:import to the https namespace and schema location over https to the virtual directory
- Modify soapAction to https
- Modify soapAddress location in <wsdl:service> to https URI pointing to the service file
Individual xsd files
- Modify xmlns:tns and targetNamespace values to https://www.myserver.com/Service/XsdFile1
- Basically xsd schema location would have been like ?xsd=xsd0/1… We will hard code this to certain file
- And the same approach can be followed for other xsd files
Once all the individual changes are made. These wsdl/ xsd files can be published to the IIS virtual directory. So, next time whenever the metadata request will be made – it will point to the hard coded paths in the wsdl and xsd files.
If you are publishing via visual studio, please ensure to change the Build Action for those files to Content type.
How can service make local metadata available?
Modify service behavior in the web.config as the following:
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" externalMetadataLocation="https:// www.myserver.com/ Service /TestService.wsdl" />
Use basciHttpBinding for simplicity sake:
<security mode="None" />
- The time can only be saved if proper namespace pattern is followed while designing the contracts for your WCF service.
- The process is purely manual. Pay keen attention and modify schemaLocation and namespace to https based url (all will associate to the newly create metadata files and be available in IIS virtual directory explicitly).
- Though the service will be accessible on https, it still runs on http inside server box.
- Approach 2 is recommended in comparison in case of non-.net client (tested in case of Java client).
Purna Chandra Panda (MSFT)