Set Manual Proxy in wcf basicHttpBinding - c#

Below is my code for setting user specified proxy address.
private Binding GetBinding()
{
BasicHttpBinding basicHttpBinding = new BasicHttpBinding(BINDING_CONFIG_NAME);
basicHttpBinding.UseDefaultWebProxy = false;
basicHttpBinding.BypassProxyOnLocal = true;
basicHttpBinding.ProxyAddress = new Uri("http://10.222.22.22:3988");
return basicHttpBinding;
}
I keep getting wrong Uri format error. What could be the right way to set Manual Proxy Address ?
And, It's working fine if I test with Default IE Proxy Settings. Thanks.
Edit : below is the code for setting endpoint.
ApptServiceClient client = new ApptServiceClient
(GetBinding(), new EndpointAddress(this.Uri));
client.Open();

Related

Secured selfhosted WCF service: load certificate from file

I have a selfhosted WCF service publishing a REST web API. The service is configured programmatically, and currently is correctly working via HTTP.
Now I need to make it work over HTTPS, with an authentication based on certificate file.
I know the suggested way to do this is installing the certificate in the Windows Certificate Store on the server machine, but this way is not possible in my circumstances.
I need to load the certificate from the file.
After some resarches, I wrote my code, but when I try accessing the web service, a System.ServiceModel.CommunicationException is thrown, with the message:
An error occurred while making the HTTP request to ... This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could also be caused by a mismatch of the security binding between the client and the server.
Here's my code for the server side:
_host = new WebServiceHost(_hostedService, Uri);
//Configuring the webHttpBinding settings
var httpBinding = new WebHttpBinding();
httpBinding.Security.Mode = WebHttpSecurityMode.Transport;
httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
httpBinding.SendTimeout = new TimeSpan(0, 5, 0);
httpBinding.MaxBufferSize = 2147483647;
httpBinding.MaxBufferPoolSize = 2147483647;
httpBinding.MaxReceivedMessageSize = 2147483647;
httpBinding.ReaderQuotas.MaxDepth = 2147483647;
httpBinding.ReaderQuotas.MaxStringContentLength = 2147483647;
httpBinding.ReaderQuotas.MaxArrayLength = 2147483647;
httpBinding.ReaderQuotas.MaxBytesPerRead = 2147483647;
httpBinding.ReaderQuotas.MaxNameTableCharCount = 2147483647;
//Add the endpoint with the webHttpBinding settings to the WebServiceHost configuration
_host.AddServiceEndpoint(typeof(IService), httpBinding, Uri);
ServiceDebugBehavior stp = _host.Description.Behaviors.Find<ServiceDebugBehavior>();
stp.HttpHelpPageEnabled = false;
ServiceBehaviorAttribute sba = _host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
sba.InstanceContextMode = InstanceContextMode.Single;
ServiceMetadataBehavior smb = new ServiceMetadataBehavior() { HttpsGetEnabled = true };
_host.Description.Behaviors.Add(smb);
X509Certificate2 trustedCertificate = new X509Certificate2("certificate.pfx", "password");
_host.Credentials.ServiceCertificate.Certificate = trustedCertificate;
_host.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
Here's my code for the client side:
var httpBinding = new WebHttpBinding();
httpBinding.Security.Mode = WebHttpSecurityMode.Transport;
httpBinding.Security.Transport = new HttpTransportSecurity() { ClientCredentialType = HttpClientCredentialType.Certificate };
var httpUri = new Uri(String.Format("https://{0}:{1}", ipAddress, tcpPort));
var httpEndpoint = new EndpointAddress(httpUri);
var newFactory = new ChannelFactory<IService>(httpBinding, httpEndpoint);
newFactory.Endpoint.Behaviors.Add(new WebHttpBehavior());
X509Certificate2 trustedCertificate = new X509Certificate2("certificate.pfx", "password"); //SSL
newFactory.Credentials.ClientCertificate.Certificate = trustedCertificate;
var channel = newFactory.CreateChannel();
var response = channel.Ping("helo");
The Exception is thrown on the last line (channel.Ping("helo")).
I need to make it work WITHOUT installing the certificate on the server machine.
Thank you very much.
Bye.
As far as I know, when we host the self-hosted WCF service over Https, whatever way we use (load certificate file or configure the certificate via Windows Certificate Store), it is impossible to make the service works normally. The only way we need to do is binding the certificate manually by using the following command.
netsh http add sslcert ipport=0.0.0.0:8000 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF}
Here is official document, wish it is useful to you.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-a-port-with-an-ssl-certificate
https://learn.microsoft.com/en-us/windows/desktop/http/add-sslcert
Here are some examples were ever written by me.
WCF Service over HTTPS without IIS, with SSL Certificate from CERT and KEY strings or files
Chrome (v71) ERR_CONNECTION_RESET on Self Signed localhost on Windows 8 Embedded
Feel free to let know if there is anything I can help with.

WCF Tcp binding in code issue

I've got a strange problem: I have a wcf service which needs to be hosted by tcp protocol on a standalone console application.
I have created a new console app project and added a lib reference for my wcf project. The problem occurs when I want to configure and broadcast the host.
var Uri = new Uri("net.tcp://myaddress:4322/MyService");
MyServiceHost = new ServiceHost(typeof(ImyService), Uri);
var binding = new NetTcpBinding();
MyServiceHost.AddServiceEndpoint(typeof(IImageExchangeService), binding, "");
var mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
MyServiceHost.AddServiceEndpoint(typeof(IMetadataExchange),mexBinding, "");
ServiceMetadataBehavior serviceBehavior = new ServiceMetadataBehavior();
serviceBehavior.HttpGetEnabled = true;
serviceBehavior.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
MyServiceHost.Description.Behaviors.Add(serviceBehavior);
When it comes to open the host, I get this message:
The contract name 'IMetadataExchange' could
not be found in the list of contracts implemented by the service WcfService.Ser
vices.MyService. Add a ServiceMetadataBehavior to the configuration
file or to the ServiceHost directly to enable support for this contract.
Now that I have better time to check this.
First you need to get the service behavior from the host or create a new one and add it if not found.
Setting the HttpGetEnabled requires you to also ad a metadata uri to the baseaddresses.
Also it does not seem to matter if the metadata endpoint is named "mex", as long as all endpoints added have unique names. So you can't use empty string for both endpoints.
var Uri = new Uri("net.tcp://myaddress:4322/MyService");
var MetadataUri = new Uri("http://myaddress:8000/MyService");
var MyServiceHost = new ServiceHost(typeof(MyService), Uri, MetadataUri);
var serviceBehavior = MyServiceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (serviceBehavior == null)
{
serviceBehavior = new ServiceMetadataBehavior();
MyServiceHost.Description.Behaviors.Add(serviceBehavior);
}
serviceBehavior.HttpGetEnabled = true;
serviceBehavior.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
MyServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
var binding = new NetTcpBinding();
MyServiceHost.AddServiceEndpoint(typeof(IImageExchangeService), binding, "image");

Remove Timestamp from WSSE Security Header C# ASMX/WCF Service

I have added a Java WSDL in my project as Web Reference. I am consuming it to call a service on an endpoint. I have added a WebMethod in an ASMX file and calling the service there. The requirement is to use WSE Security and sign the request with X509 Certificate.
Unfortunately, the Timestamp is creating issues and I am getting the response " An error was discovered processing the header". The Same request works from SoapUI if I remove the TimeStamp element from it.
This is how the request look like
Here is the code which creates the Security elements
//Set WSSE Security
svc.RequestSoapContext.Security.Timestamp.TtlInSeconds = 300;
svc.RequestSoapContext.Security.MustUnderstand = true;
svc.RequestSoapContext.Security.Tokens.Add(newtoken);
Microsoft.Web.Services3.Security.MessageSignature signature = new Microsoft.Web.Services3.Security.MessageSignature(newtoken);
signature.SignatureOptions = Microsoft.Web.Services3.Security.SignatureOptions.IncludeSoapBody;
svc.RequestSoapContext.Security.Elements.Add(signature);
===============
USING WCF
The problem persists even if I do it using WCF. As soon as I add IncludeTimestamp = false; the request is not getting sent and setting it to true is able to create request.
Here is the WCF Code -
//Create Endpoint
EndpointAddress address = new EndpointAddress((istest == true ? CHORUS_UFB_EMMA : CHORUS_UFB_PROD));
//Add Certificate to EndPoint Service
X509Certificate2 cert = new X509Certificate2(#"Certificate Path", "Password", X509KeyStorageFlags.PersistKeySet);
//Setup custom binding with HTTPS + Body Signing + Soap1.1
CustomBinding binding = new CustomBinding();
//HTTPS Transport
HttpsTransportBindingElement transport = new HttpsTransportBindingElement();
//Set Security Binding as Transport
TransportSecurityBindingElement tsec = SecurityBindingElement.CreateCertificateOverTransportBindingElement(MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConvers‌​ation13WSSecurityPol‌​icy12BasicSecurityPr‌​ofile10);
tsec.EnableUnsecuredResponse = true;
tsec.AllowInsecureTransport = true;
tsec.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
tsec.LocalServiceSettings.DetectReplays = false;
tsec.LocalClientSettings.DetectReplays = false;
tsec.IncludeTimestamp = false;
tsec.SetKeyDerivation(false);
tsec.EndpointSupportingTokenParameters.Signed.Add(new SecureConversationSecurityTokenParameters());
//Setup for SOAP 11 and UTF8 Encoding
TextMessageEncodingBindingElement textMessageEncoding = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
//Bind in order (Security layer, message layer, transport layer)
binding.Elements.Add(tsec);
binding.Elements.Add(textMessageEncoding);
binding.Elements.Add(transport);
Here is the generated request using above code
Any help on this would be appreciated.
This could potentially be caused by time differences between your client and the web server where the service you are calling is hosted.
Double check if the time on both servers match and are in sync. Times might need to be within 5 minute window.

WCF basicHttpBinding and HTTP proxy

I'm trying to get my generated WCF ServiceClient to send its requests to the WCF service through a HTTP (not HTTPS) proxy with username/password authentication, however I just can't get it work. My WCF service uses basicHttpBinding so I tried to configure my ServiceClient instance like so:
var svc = new ServiceClient();
var b = svc.Endpoint.Binding as BasicHttpBinding;
b.ProxyAddress = new Uri(proxyAddress);
b.UseDefaultWebProxy = false;
b.Security.Mode = BasicHttpSecurityMode.Transport;
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
b.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Basic;
svc.ClientCredentials.UserName.UserName = proxyUsername;
svc.ClientCredentials.UserName.Password = proxyPassword;
This however results in a System.ArgumentException saying:
The provided URI scheme http is invalid. expected https
When I set the b.Security.Mode to BasicHttpSecurityMode.None though, it seems the HTTP proxy settings are ignored by WCF altogether!
The second solution I tried was to set the DefaultWebProxy property of WebRequest and set the UseDefaultWebProxy property to true such as so:
var webProxy = new WebProxy(proxyAddress, true);
webProxy.Credentials = new NetworkCredential(proxyUsername, proxyPassword);
WebRequest.DefaultWebProxy = webProxy;
var svc = new ServiceClient();
var b = svc.Endpoint.Binding as BasicHttpBinding;
b.UseDefaultWebProxy = true;
However this also doesn't work and ServiceClient doesn't send it's requests through the HTTP proxy.
I'm out of ideas here so please let me know what I am doing wrong, thank you!
Set the security mode to BasicHttpSecurityMode.TransportCredentialOnly. This allows for passing plain-text authentication details over HTTP.

Why do I get WCF Exception "HTTP could not register URL http://+:80/MyService/"

I create my host with the endpointaddress it needs to use, like this:
Uri endpointAddress = new Uri("http://127.0.0.1:5555/MyService");
ServiceHost host = new ServiceHost(myServiceType, endpointAddress);
host.AddServiceEndpoint(implementedContract, basicHttpBinding, string.Empty);
but when I later do host.Open(); I get the exception "HTTP could not register URL http://+:80/MyService/ because TCP port 80 is being used by another application". The result is the same when I do
host.AddServiceEndpoint(implementedContract, basicHttpBinding, endpointAddress);
Why would it try to do anything with port 80? How can I solve this?
Update
While trying to provide a more complete code sample, I found the culprit. I added a ServiceMetadataBehavior as follows:
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.ExternalMetadataLocation = new Uri(this.ExternalMetadataLocation);
smb.HttpGetEnabled = true;
smb.HttpGetUrl = this.RemovePort(this.EndpointAddress);
host.Description.Behaviors.Add(smb());
It seems that in the past I needed to remove the port from the URL to get this to work, but now that's exactly what causes the problem.
So Pratik is right: metadata were the problem, and of course the problem with port 80 is that there's some newly installed application using that port.
Thanks, regards,
Miel.
This is because port 80 is already used by another applicatiion as the error message says, most likely by local IIS server. Try stopping IIS and see, or use another port.
On vista and above you can use netsh command to check which ports are already reserved
BTW do you have http metadata or mex endpoints in the app.config or web.config file ?
The following works fine for me:
class Program
{
[ServiceContract]
public interface IMyService
{
[OperationContract]
void Test();
}
public class MyService : IMyService
{
public void Test()
{
throw new NotImplementedException();
}
}
static void Main()
{
var endpointAddress = new Uri("http://127.0.0.1:5555/MyService");
using (var host = new ServiceHost(typeof(MyService), endpointAddress))
{
var basicHttpBinding = new BasicHttpBinding();
host.AddServiceEndpoint(typeof(IMyService), basicHttpBinding, string.Empty);
host.Open();
}
}
}
Maybe you have some other code which is interfering?

Categories

Resources