We would like to keep the WCF in the configuration file.
At the same time we would like the code to refuse a request if the data will be sent over the net unencrypted. Something like: if the request is basichttpbinding without https, throw exception.
Is there any way for the service code to know how it is being called?
EDIT
From the comments it looks like the question was not that clear.
What I am trying to do is "fix" the following situtaion: We install a service with basichttpBinding and https. Then a administrator changes it to not use https. The effect is that data is sent unencrypted over the net.
I'm not sure I understand what you want... are you talking about validating, on the service itself, how it is being called and reject some requests if they don't meet certain criteria?
I'm sure that can probably be done (at least certain things, like checking for SSL are more or less simple), but first I'd ask why, if you only want your service called over secure bindings, why you're exposing the service using unsecured ones in the first place. Doesn't it make more sense to ensure the service configuration is correct?
Are you self-hosting?? The most simplistic approach would be:
ServiceHost serviceHost = new ServiceHost(typeof(Service1), "http://localhost:1234/MyService/xml");
foreach (ServiceEndpoint sep in serviceHost.Description.Endpoints)
{
if(sep.Binding.Scheme != "https")
{
// either just remove that endpoint, or signal an error
}
}
Of course, when you host in IIS, this gets a bit trickier... you might have to create your own custom ServiceHost descendant to do this check, and make sure your IIS based *.svc files use that custom host. Of course, a smart admin might be able to trick that by using the base ServiceHost instead of your own custom host class......
I don't have an example for you, but keep in mind that anything you can do through configuration with WCF, you can do in code. You don't even need to have a configuration file.
Related
I have an existing WCF service, written in C#, which is hosted in an own process (not in IIS). Now I want to re-configure this service, so that the following requirements are met:
It has to use basicHttpBinding
It has to use SSL
No code changes, just changes in the service's and client's .exe.config file
Username and password authentication; as there is only one known client, a single hard-coded username/password would be sufficient
I have already searched pretty much but it seems that 4. and 3. are not possible in this combination. The ideal thing would be if one could just hard-code a username and password in the service's .exe.config file. Is this possible at all?
If yes, how would such a config file look like?
If no, what would be feasible alternatives, meeting requirements 1.-3. and what would their config file look like?
To get 1 through 3 try the following (Really no code changes just configuration and setup):
SSL with Self-hosted WCF Service
However 4, I think, will be impossible without code changes you will need to provide that user name/password to the service somehow and then on the service do a check for it. Configuration wont save you there, need to roll up your sleeves and put down some C# .NET!
I am trying to consume a WCF web service from a .NET client application, and I think I need to be able to programmatically create endpoints, but I don't know how. I think I need to do this because, when I try to run the application, I am getting the following error:
Could not find default endpoint
element that references contract
'IEmailService' in the ServiceModel
client configuration section. This
might be because no configuration file
was found for your application, or
because no endpoint element matching
this contract could be found in the
client element.
While troubleshooting this error, I created a simple windows forms application, in which I try to consume the same web service. With this test application I can connect to the web service successfully, and I get a valid response. But, I can reproduce the exact error cited above within in my test app by removing the system.serviceModel node and all of its child nodes from the application's app.config file (I might not have to remove ALL of that section, I'm not sure). So, my first thought was that I need to add that section to the app.config file for the real app, and everything should be fine. Unfortunately, for ridiculous reasons that I won't get into here, that is not an option. So, I am left with having to generate this information in code, inside the client app.
I am hoping someone here can help me work through this, or can point me toward a good resource for this sort of problem.
Is it possible to create endpoint configurations in the client app, in code?
By default, when you do an Add Service Reference operation, the WCF runtime will generate the client-side proxy for you.
The simplest way to use it is to instantiate the client proxy with a constructor that takes no parameters, and just grab the info from the app.config:
YourServiceClient proxy = new YourServiceClient();
This requires the config file to have a <client> entry with your service contract - if not, you'll get the error you have.
But the client side proxy class generated by the WCF runtime also has additional constructors - one takes an endpoint address and a binding, for instance:
BasicHttpBinding binding = new BasicHttpBinding(SecurityMode.None);
EndpointAddress epa = new EndpointAddress("http://localhost:8282/basic");
YourServiceClient proxy = new YourServiceClient(binding, epa);
With this setup, no config file at all is needed - you're defining everything in code. Of course, you can also set just about any other properties of your binding and/or endpoint here in code.
An east way to consume a WCF service if you have a reference to the assembly which defines the interface, is using the System.ServiceModel.ChannelFactory class.
For example, if you would like to use BasicHttpBinding:
var emailService = ChannelFactory<IEmailService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress(new Uri("http://some-uri-here.com/));
If you don't have a reference to the service assembly, then you can use one of the overloaded constructors on the generated proxy class to specify binding settings.
I have a WCF Service that I want my client to be able to consume from IIS without going through a proxy. The client was consuming asmx service in vbscript using the htc behavior:
<div id="oWSInterop" style="behavior:url(webservice.htc)"></div>
oWSInterop.useService "http://localhost/WSInteroperability.asmx", "WSInteroperability"
Set response = oWSInterop.WSInteroperability.callServiceSync("BuildSingleDoc", 1002, 19499, XMLEncode(sAdditionalDetail))
So basically I just want to make this work with making as few changes as possible on the existing client. Am I forced to use a proxy (that is, a class on the client side that exposes the operations in the WCF service) when consuming a WCF service? I do understand the benefits of a proxy and am not opposed to using it for most other client implementations, but in this case I'm not sure I have the time to deal with it on the client - i just want it to work the way it has been with only the endpoint changing.
A client-side proxy class to call the service?
Yes, you definitely need that (unless you do REST-based WCF services, which you can call with a HttpClient alone) - that's where the whole WCF runtime lives and does its magic.
If you want to call up REST-based services, you can do this without any proxy whatsoever - but then you're left to do XML or JSON parsing yourself. It can be done, but it might not be such a great idea.
What's the problem with the proxy?? It's really just a small wrapper that bundles up your calls into a serialized message and sends it to the server side. No big harm, in my opinion....
What are you seeing? What makes you thank that proxy is an issue? If that is server-side code, it should use the browsers settings (WinINet) which should work fine. Perhaps the "localhost" would be an issue, though, since to the client that still means "talk to yourself" (i.e. not the server).
If that is server side you'll probably need to configure WinHTTP appropriately; in particular, to skip the proxy for local addresses. Of course, "localhost" should loop-back anyway...
Let's say you've got a WCF service that is accessible via HTTP and HTTPS, but you want only certain methods to be available with HTTPS-- how can I check if the current request is HTTPS? Since HttpContext is empty, you can't simply check HttpContext.Current.Request.IsSecureConnection -- any other ideas? Thanks in advance.
Consider that WCF applications can also be hosted as a Windows service, with no ASP.NET at all, in which case there is no such thing as "secure" vs. "insecure." That is one reason why WCF does not attempt to make this information available.
One option would be to run the WCF service in ASP.NET Compatibility Mode, where you do have access to the HttpContext.Current instance.
My choice, however, would simply be to create a different, SSL-only service for the secure operations. I really think you'd want to do this anyway, so the contract is explicit; otherwise you're left doing runtime checks and clients may have no idea that the methods they're trying to use aren't allowed.
"Best practice" in a web service is to make these types of restrictions as explicit as possible, and having a separate service available only over SSL is by far the clearest means of describing your service's restrictions.
( Building on comment from #Aaronaught within answer by Matt Ellen... )
It looks like
OperationContext.Current.RequestContext.RequestMessage.Headers.To.Scheme
contains "http" or "https" among others (msdn).
HTTPS is served over a different port to HTTP. Assuming you know the ports, perhaps checking that would suffice.
How about:
var iwrc = WebOperationContext.Current.IncomingRequest;
var isHttps = iwrc.UriTemplateMatch.BaseUri.Scheme.Equals("https", StringComparison.InvariantCultureIgnoreCase);
This is very easy, does not rely on port numbers and works just fine in a self-host WCF server (with no IIS in site sight).
I am validating users using the UserNamePasswordValidator.Validate(string username, string password) and the service is hosting itself (e.g. no IIS).
The problem I have is that if the user fails the validation I want to track the users IP address. This works fine of the user gets validated, because then the OperationContext has been initialized (it is null inside the validate method and not created until later).
Does anyone know how to get the clients IP address either in the validate method or before the validate method has been executed?
Yes, I know about how to get the IP address using RemoteEndpointMessageProperty but like I said, it never get that far if validation fails :-)
I've researched this to death all week, and I can't come up with a single blog entry or MSDN article that deals with the issue.
As far as I can tell, you cannot log IP address during the Validate stage.
The only workaround I can suggest is to host in IIS and use the weblogs there, which do log IP address. It's painful, unfortunately, but it may be the only way.
If you're hosting in IIS then this becomes much more simple. This chunk of config comes straight from my hosting web project and forces ASP.NET requests to come down the IIS pipeline rather than being dispatched straight to the ASP err bits of IIS.
aspNetCompatibilityEnabled: When this attribute is set to
true, requests to Windows Communication Foundation (WCF) services
flow through the ASP.NET HTTP pipeline, and communication over
non-HTTP protocols is prohibited.
See: http://msdn.microsoft.com/en-us/library/ms731336.aspx
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
I use the AuthenticationService and make use of the HttpContext to get at all the interesting stuff about the client, much of it is useful for things like ensuring a user isn't logging in from six different subnets as well as playing around with cookies.
Although I think this is applied to the MS AuthenticationService, any other services you have will need this attrib:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
If you want to pursue your non-IIS hosted service route, then I'd see what stuff is available inside the MS API using reflection, poking around on a WCF with the debugger while stopped, unfolding all those Non-public members.
I suppose the problem will be getting a reference to a bit of WCF which is initialized from which to start poking. You might have to register some kind of listener to one of the dispatchers when you setup the service host.
http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.channeldispatcher.aspx
Edit:
Adding this link as my thoughts are that you'd need to get at stuff in WCF that's right down the stack before it gets to your code:
http://blogs.msdn.com/sonuarora/archive/2007/06/11/passing-soap-actions-to-adapter-inbound-handler-for-filtering-type-of-listeners.aspx