I'm trying to get a WCF web service to work with SSL, as you can imagine it works on my machine, however when I run it on the production environments I get this instead:
Could not find a base address that matches scheme http for the endpoint with binding BasicHttpBinding. Registered base address schemes are [https].
Despite many hours of wrestling with this problem I still have very little idea what this error message actually means - googling for this error message finds loads of people saying that I should either specify an address in my endpoint configuration or add a base address to my service, however:
My service worked perfectly fine without specifying either with SSL disabled
In fact, my service works perfectly fine with SSL with the exact same configuration on another machine
Besides, I've found a post which reliably informs me that when hosting under IIS the base address is ignored anyway.
As you can probably tell, I'm currently feeling a very fustrated at my utter failure to achieve what I believed to be a relatively simple task, so:
What does this error message actually mean?
How are base addresses determined when hosting under IIS?
Where can I find reliable, understandable documentation about what all of my copy-pasted configuration actually means?
What do I need to do to get my service to actually work?
The interesting bits of my web.config are:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<services>
<service name="MyService" behaviorConfiguration="MyBehavior">
<endpoint binding="basicHttpBinding" bindingConfiguration="SecureTransport"
bindingNamespace="http://MyNamespace/Service" name="Basic"
contract="MyContract" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyBehavior">
<serviceMetadata httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="SecureTransport">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
One thing that is off field but can cause this message is if the SSL certificate on the server is expired or not set up correctly.
Related
It's really hard to pick up web services if you're a beginner, not because the concept is hard - it isn't - but because the technology has gone through a lot of twists and turns and googling for help doesn't help if all you get back are answers for implementations done slightly differently.
[For example our solution has never had a .svc file or .asmx file though those turn up regularly in answers and our web.config doesn't have any behavior or binding element, as others seem to have]
We've used a tutorial to set up what I think is termed a "WCF Web Service" running on IIS6. It's working fine.
But we'd like to convert it to use encryption/https.
So we've checked the Require secure channel box in IIS:
Not sure what else to configure in there, but ... anyway, moving on. Next I'd imagine we have to modify our web.config file ... but what and how? Here's what we've got under system.serviceModel in our web.config:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"></serviceHostingEnvironment>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"></standardEndpoint>
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
So what do we need to do next?
Ok, so it's hard to be prescriptive without ALL of the code unfortunately, but here's the overview:
You'll want to add those bindings and behaviors into the web.config.
I'd start with a basicHttpBinding, and just make it work like it does currently, but this time you'll be specifying your binding details instead of using defaults. To "turn off" https, change the Security mode in the bindingConfiguration to None.
You'll have something like this for your WCF service when you are done:
<services>
<service behaviorConfiguration="webServiceClientBehavior" name="My.Service.ServiceName">
<endpoint address="http://localhost:5803/LSClient" binding="basicHttpBinding" bindingConfiguration="secureBinding" contract="My.Service.IServiceName"/>
</service>
</services>
For the bindingConfiguration:
<bindings>
<basicHttpBinding>
<binding name="secureBinding">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
For the behaviorConfiguration:
<serviceBehaviors>
<behavior name="webServiceClientBehavior">
<!--For MetaData-->
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:5802/LSClientMD"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
These will need to be adjusted slightly for your implementation, but that's a basic overview.
I've set up a WCF service to require NTLM authentication using the following configuration:
<system.serviceModel>
<bindings>
<customBinding>
<binding name="BinarySecurityBinding">
<binaryMessageEncoding/>
<httpTransport authenticationScheme="Ntlm"/>
</binding>
</customBinding>
</bindings>
<services>
<service name="Services.LogisticsServices" behaviorConfiguration="ServiceBehavior">
<endpoint address="" binding="customBinding" bindingConfiguration="BinarySecurityBinding" contract="Services.ILogisticsServices" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I did this so that the applications that consume the web service are forced to log in because all my service's operations use impersonation ([OperationBehavior(Impersonation = ImpersonationOption.Required)]).
In IIS 7 I've enabled anonymous and Windows authentication.
When I visit http://test.server/LogisticsServices.svc, which hosts the service described above, I can see the default service description page anonymously. However, when Visual Studio tries to access http://test.server/LogisticsServices.svc/$metadata to generate a client proxy, the server is responding with HTTP code 401 and expecting authentication. Not only would I've expected the metadata to be available anonymously, but additionally, the server is not accepting the credentials I am giving it (even though, I know for a fact that they are correct).
Testing different configuration, I tried removing the authenticationScheme from my binding's transport, just to be able to generate the client proxy, but that results in an exception because the service's operations require impersonation ([OperationBehavior(Impersonation = ImpersonationOption.Required)]).
What am I missing in my service's configuration that would make the service's metadata available anonymously? I'm also open to suggestions if I'm approaching the whole thing wrong.
here is a similar discussion:
Getting an Security setting exception while accessing a WCF service
One way around this is not to use the autogenerated proxies.
In cases where we have control over both the server and the client we have found that it is much more productive to avoid using the autgenerated proxies.
A screencast of how to do this can be found here: http://www.dnrtv.com/default.aspx?showNum=122
You could try imperative instead of declarative model, see: http://msdn.microsoft.com/en-us/library/ms730088.aspx
I wrote a WCF service hosted by IIS 6 on a server that is not part of a domain. It uses the following configuration:
<system.serviceModel>
<services>
<service behaviorConfiguration="ServiceBehavior" name="Services.DeliveryStatsService">
<endpoint address="" binding="customBinding" bindingConfiguration="BindingWithMaxClockSkewForIncorrectlyConfiguredWindowsServer"
contract="Services.IDeliveryStatsService" />
</service>
</services>
<bindings>
<customBinding>
<binding name="BindingWithMaxClockSkewForIncorrectlyConfiguredWindowsServer">
<binaryMessageEncoding />
<security>
<localClientSettings maxClockSkew="00:20:00" />
<localServiceSettings maxClockSkew="00:20:00" />
<secureConversationBootstrap />
</security>
<httpTransport />
</binding>
</customBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
It would've been a simple basicHttpBinding, except that the server's clock is not set to the right time and its administrator will not change that, so a customBinding is required to allow for "clockSkew."
Clients use pretty much the same configuration (binding-wise) and can access the service without any trouble, as long as they are not part of a domain. However, clients that are part of a domain are rejected with the message "The caller was not authenticated by the service."
I turned on tracing and it would seem that the problem comes from a token exchange using SSPI negociation. Unfortunately, I can't seem to find the right configuration that will allow both machines that are not part of a domain and machines that are part of a domain to access the service. I have tried several values for authenticationMode, without avail. What's more, as far as I'm concerned, I don't need any particular security on this service.
WCF configuration is far from being my specialty and I haven't found an answer anywhere else, so I hope someone at Stack Overflow will be able to help. Thanks in advance.
Why do you need to set maxClockSkew when you don't need security? It is for handling time differences in timestamps which are not send without security. Once you add security element you turn on authentication because all attributes in the element have default values. Default value for mode is sspiNegotiated. I would start with removing security element.
I have a simple WCF service (hosted as its own site in IIS). It was originally developed targeting .NET 4 but I have recently discovered that it needs to be downgraded to .NET 3.5.
I never touched the web.config file and it Just Worked. Now that I've changed the project from .NET 4 back to 3.5 I'm getting config errors. The first one was about multipleSiteBindingsEnabled not being recognised - a quick search tells me this is new in .NET 4 so I just deleted it. Now the error I'm getting is:
Service 'MyService' has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.
I just want to get the service responding so I can test firing things at it. The system that will be consuming the service doesn't exist yet (it's currently being developed by a government department) so once that's closer to completion we'll be worrying about the config that will be needed for it to go into production etc. What's the minimum config I need in the web.config to make it work for testing?
You need these basic nodes in your service's web.config files usually.
Of Course the binding types / dedub config / etc is all just for testing.
You need to fine tune it as per your needs
<system.serviceModel>
<services>
<service name="A.B.C.D" behaviorConfiguration="returnFaults">
<endpoint contract="A.B.C.ID" binding="basicHttpBinding" address=""/>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="HttpBinding" maxReceivedMessageSize="2097152">
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="returnFaults">
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Has anyone ever tried to use custom binding with SSL in a WCF web service? I've seen a number of examples on how to do this with basicHttpBinding and wsHttpBinding but the equivalent always fails for customBinding. Specifically what I'm currently working with (the most successful configuration yet) looks something like this:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
</serviceHostingEnvironment>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="binaryHttps">
<binaryMessageEncoding />
<httpsTransport />
</binding>
</customBinding>
</bindings>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="MyService">
<host>
<baseAddresses>
<add baseAddress="https://(myserver)/"/>
</baseAddresses>
</host>
<endpoint address=""
binding="customBinding" bindingConfiguration="binaryHttps"
contract="MyService" />
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
This actually allows us to access the service from the web, get it's WSDL and add a service reference inside visual studio alright, but when we actually try and use it live in our silverlight-3 application, it just sits there indefinitely waiting for a response and never times out. It actually ends up giving me low memory problems after a while on my machine (with 6GB of memory). The odd thing is that all this worked (and still does) perfectly in the development environment (using strictly the VS application hosts), it wasn't until we tried to deploy it to an actual server with a real SSL certificate that all these issues popped up.
I've searched fairly exhaustively for a solution to this problem but have so far not found anything and have tried just about everything - Is there anyone out there that's encountered this before and got around it?
So it turns out the problem wasn't with our web.config at all, it had to do with an issue with IIS 7 and Wildcard SSL certificates.
Namely, IIS 7 doesn't allow you to specify the hostname when binding an IP to an SSL connection and certificate. I'd guess that this is because it expects a non-wildcard SSL certificate that it can extract the explicit hostname from. What we ended up having to do was to go into the applicationHost.config file in {WindowsDir}\{System32}\{Inetsrv}\{config} and find the entry with our web service's bound IP address and change it explicitly to (ip):(hostname). It was then even displayed properly in the IIS config GUI.
After doing this we were to completely turn off all but SSL channels on all our servers and everything worked beautifully.
Thank god that's over!
AFAIK, using SSL has performance problem. We are using WCF behiovr to do the authentication. The way that we are using is that Silverlight => ASP.NET => WCF. We configured the Endpoint behivor in both Silverlight and WCF. Whenever we call the service, we passed the token for authentication.
Are you saying that you can use custom binding in ClientConfig of Silverlight?