WCF client binding configuration in program code - wcf

I have the following class that configures security, encoding, and token parameters but I am having trouble adding a BasicHttpBinding to specify a MaxReceivedMessageSize. Any insight would be appreciated.
public class MultiAuthenticationFactorBinding
{
public static Binding CreateMultiFactorAuthenticationBinding()
{
HttpsTransportBindingElement httpTransport = new HttpsTransportBindingElement();
CustomBinding binding = new CustomBinding();
binding.Name = "myCustomBinding";
TransportSecurityBindingElement messageSecurity = TransportSecurityBindingElement.CreateUserNameOverTransportBindingElement();
messageSecurity.AllowInsecureTransport = true;
messageSecurity.EnableUnsecuredResponse = true;
messageSecurity.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12;
messageSecurity.SecurityHeaderLayout = SecurityHeaderLayout.Strict;
messageSecurity.IncludeTimestamp = true;
messageSecurity.SetKeyDerivation(false);
TextMessageEncodingBindingElement Quota = new TextMessageEncodingBindingElement(MessageVersion.Soap11, System.Text.Encoding.UTF8);
Quota.ReaderQuotas.MaxDepth = 32;
Quota.ReaderQuotas.MaxStringContentLength = Int32.MaxValue;
Quota.ReaderQuotas.MaxArrayLength = 16384;
Quota.ReaderQuotas.MaxBytesPerRead = 4096;
Quota.ReaderQuotas.MaxNameTableCharCount = 16384;
X509SecurityTokenParameters clientX509SupportingTokenParameters = new X509SecurityTokenParameters();
clientX509SupportingTokenParameters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
clientX509SupportingTokenParameters.RequireDerivedKeys = false;
messageSecurity.EndpointSupportingTokenParameters.Endorsing.Add(clientX509SupportingTokenParameters);
//binding.ReceiveTimeout = new TimeSpan(0,0,300);
binding.Elements.Add(Quota);
binding.Elements.Add(messageSecurity);
binding.Elements.Add(httpTransport);
return binding;
}
}

If you need to specify MaxReceivedMessageSize you can do it on your transport binding element - HttpsTransportBindingElement. You can't add binding to binding.

Just Found this to create a BasicHttpBinding
BasicHttpBinding Basicbinding = new BasicHttpBinding(BasicHttpSecurityMode.None);
Basicbinding.MaxReceivedMessageSize = 10000000;

Related

Unable to modify a:To element of WCF addressing header. a:To header is not available in ClientMessageInspector.BeforeSendRequest

I'm trying to modify the value of a:To addressing header element. a:To element is not available in BeforeSendRequest of ClientMessageInspector.
If I add it in BeforeSendRequest, then it is overridden with the endpoint.
var toHeader = MessageHeader.CreateHeader("To", "http://www.w3.org/2005/08/addressing", "https://toHeaderValue", true);
request.Headers.Add(toHeader);
I'm here using the CustomBinding with Soap version 1.1 and Addressing version 10
{
HttpTransportBindingElement bindingElement;
var binding = new CustomBinding
{
Name = "*******",
OpenTimeout = TimeSpan.FromMinutes(10),
CloseTimeout = TimeSpan.FromMinutes(10),
SendTimeout = TimeSpan.FromMinutes(10),
ReceiveTimeout = TimeSpan.FromMinutes(10)
};
binding.Elements.Add(new TextMessageEncodingBindingElement
{
MessageVersion =
MessageVersion.CreateVersion(EnvelopeVersion.Soap11,
AddressingVersion.WSAddressing10),
WriteEncoding = Encoding.UTF8
});
bindingElement = GetBindingElement(url);
bindingElement.ManualAddressing = false;
bindingElement.MaxReceivedMessageSize = 20000000;
bindingElement.AllowCookies = false;
bindingElement.BypassProxyOnLocal = false;
bindingElement.MaxBufferSize = 20000000;
bindingElement.TransferMode = TransferMode.Buffered;
bindingElement.AuthenticationScheme = AuthenticationSchemes.Anonymous;
bindingElement.ProxyAuthenticationScheme = AuthenticationSchemes.Anonymous;
bindingElement.UseDefaultWebProxy = true;
binding.Elements.Add(bindingElement);
return binding;
}
private HttpTransportBindingElement GetBindingElement(string url)
{
if (Uri.TryCreate(url, UriKind.Absolute, out var uriResult) && uriResult.Scheme == Uri.UriSchemeHttp)
return new HttpTransportBindingElement();
else
return new HttpsTransportBindingElement();
}
Maybe the solution is set this:
var endpoint = new EndpointAddress
(
new Uri("a to address"),
new DnsEndpointIdentity("endpoint identity"),
new AddressHeaderCollection()
);
And set the value to header:
client.Endpoint.Behaviors.Add(new ClientViaBehavior(new Uri("address")));
Hope it helps.

Consume WCF service in Xamarin Forms

I can integrate the WCF service in xamarin with .net framework class library file.
WCF - Developed in .net Framework 4.5
Xamarin - Developing in .net Core 2.2
Here I am unable to consume the WCF service created with .net framework. But I can consume the service where I as created the Asp.Net project with same .net framework version.
What need to do to consume it in xamarin
Hi Colin / Jason / Hakim.....
there is no issue while consuming the WCF with ASP.net which was created both in the same framework. But unable to consume in Xamarin... Below is the code...
public class Class1
{
public UserInfo GetUser(string username, string password)
{
WSHttpBinding binding = new WSHttpBinding();
TimeSpan span = new TimeSpan(0, 3, 0);
binding.Name = "WSHttpBinding_IService";
binding.CloseTimeout = span;
binding.OpenTimeout = span;
binding.ReceiveTimeout = span;
binding.SendTimeout = span;
binding.AllowCookies = false;
binding.BypassProxyOnLocal = false;
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
// binding.MaxBufferSize = 65536;
binding.MaxBufferPoolSize = 524288;
binding.MaxReceivedMessageSize = 65536;
binding.MessageEncoding = WSMessageEncoding.Text;
binding.TextEncoding = Encoding.UTF8;
//binding.TransferMode = TransferMode.Buffered;
binding.UseDefaultWebProxy = true;
binding.ReaderQuotas = new XmlDictionaryReaderQuotas();
binding.ReaderQuotas.MaxDepth = 32;
binding.ReaderQuotas.MaxStringContentLength = 8192;
binding.ReaderQuotas.MaxArrayLength = 16384;
binding.ReaderQuotas.MaxBytesPerRead = 4096;
binding.ReaderQuotas.MaxNameTableCharCount = 16384;
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
binding.Security.Transport.Realm = string.Empty;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default;
ICFService.ServiceClient client = new ServiceClient(binding, new EndpointAddress("..../Service.svc"));
client.ClientCredentials.UserName.UserName = username;
client.ClientCredentials.UserName.Password = password;
return client.CheckUser(new UserRQ() { UserName = username, Password = password });
}
}
Xamarin Button click
try
{
APIServiceLibrary.Class1 api = new APIServiceLibrary.Class1();
var user = api.GetUser(Entry_Username.Text, Entry_Password.Text);
if (user != null)
{
}
}
catch (Exception ex)
{
throw ex;
}

Xamarin with WCF has a timeout error

My app uses WCF to transfer data from server and app.It works well all along.But recently,if the app does not operate after a period of time,there's always throwing a timeout exception.When the timeout exception was thrown,winform application can call WCF normally。If restart debug,the app can call WCF again;and after a while,it throw timeout exception again.What can I do for this?
My code like this:
// CreateBinding
private static BasicHttpBinding CreateBasicHttp()
{
BasicHttpBinding binding = new BasicHttpBinding
{
Name = "basicHttpBinding",
MaxBufferSize = 2147483647,
MaxReceivedMessageSize = 2147483647
};
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
TimeSpan timeout = new TimeSpan(0, 0, 30);
binding.SendTimeout = timeout;
binding.OpenTimeout = timeout;
binding.ReceiveTimeout = timeout;
return binding;
}
// Create Endpoint
private static EndpointAddress CreateEndPoint(string serviceName)
{
string serviceUrl = App.RemoteUrl + serviceName + ".svc";
EndpointAddress EndPoint = new EndpointAddress(serviceUrl);
return EndPoint;
}
// Create binder
public static WCFBinder GetBinder<T>()
{
WCFBinder binder;
Type t = typeof(T);
string serviceName = t.Name.Substring(1, t.Name.Length - 1);
binder.Binding = CreateBasicHttp();
binder.EndPoint = CreateEndPoint(serviceName);
return binder;
}
// Create a client
var binder = SDHCommonMethod.GetBinder<IAAA001BLLService>();
IAAA001BLLService asc = new AAA001BLLServiceClient(binder.Binding, binder.EndPoint);
// Call WCF
var obj = await Task.Factory.FromAsync(asc.BeginSelectAAA001, asc.EndSelectAAA001, dto, TaskCreationOptions.None);
The code is right. In vs2017,it can work.Maybe my vs2015 has something wrong.

WSE2 to WCF: Signing a SOAP message

I need to covert code from WSE2 to WCF and need a few tips on how to implement signing a SOAP message with a X509Certificate2 object.
WSE2 code:
X509SecurityToken tok = new X509SecurityToken(cert);
SoapContext cont = cfs.RequestSoapContext;
cont.Security.Tokens.Add(tok);
cont.Security.Elements.Add(new MessageSignature(tok));
"cert" is my X509Certificate2 object and "cfs" is my Web Services client object.
How can I make this work without WSE2, how to do the same in WCF?
You can use a custom binding for that, but first you must figure out which kind of binding you need. Look here and here. On custom binding you can add security token for signing. My asymmetric binding looks like this: (but you can also use symmetric binding)
AsymmetricSecurityBindingElement asymmetricBinding = SecurityBindingElement.CreateMutualCertificateDuplexBindingElement(
MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);
asymmetricBinding.InitiatorTokenParameters = new X509SecurityTokenParameters
{
InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient
};
asymmetricBinding.RecipientTokenParameters = new X509SecurityTokenParameters
{
InclusionMode = SecurityTokenInclusionMode.Never
};
asymmetricBinding.EndpointSupportingTokenParameters.SignedEncrypted.Add(new UserNameSecurityTokenParameters
{
InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient
});
asymmetricBinding.IncludeTimestamp = true;
asymmetricBinding.SecurityHeaderLayout = SecurityHeaderLayout.Strict;
asymmetricBinding.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
var textMessageEncoding = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
var httpsTransport = new HttpsTransportBindingElement();
CustomBinding b = new CustomBinding(asymmetricBinding, textMessageEncoding, httpsTransport);
Then you can set certificates on ClientCredentials of the EndpointClient
var wsClient = new YourEndpointClient(b, new EndpointAddress(yourWsEndPointAddress));
wsClient.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(cert);
wsClient.ClientCredentials.ServiceCertificate.DefaultCertificate = new X509Certificate2(cert);

Programmatic WCF Message Security with Certificates

I've written a self-hosted WCF service using WSHttpBindings and I'm trying to implement message-level security using certificates I've generated myself. Unfortunately I'm getting a buried exception (via the Service Trace Viewer) stating "The credentials supplied to the package were not recognized."
A couple notes:
This has to be done in code, not
in configuration
(Server/Client)Cert are certificates
that are in the local machine store
with accessible private keys to my
user while debugging.
I've googled the hell out of this and
found a good resource for setting up
WCF message based security here
I'm not sure what I'm missing. Most of this stuff seems straight forward except for creating the endpoint identities. It fails with the same message whether I use DnsEndpointIdentities, cert based ones, or no identities at all.
Can anyone point me in the right direction?
Server side:
var binding = new WSHttpBinding
{
Security =
{
Mode = SecurityMode.Message,
Message =
{
ClientCredentialType = MessageCredentialType.Certificate,
AlgorithmSuite = SecurityAlgorithmSuite.Basic256Sha256Rsa15
}
}
};
_host = new ServiceHost(this)
{
Credentials =
{
ServiceCertificate =
{
Certificate = ServiceCert
},
ClientCertificate =
{
Certificate = ClientCert,
Authentication =
{
TrustedStoreLocation = StoreLocation.LocalMachine,
RevocationMode = X509RevocationMode.NoCheck,
CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust
}
}
}
};
var address = new Uri(string.Format(#"http://serviceaddress"));
var ep = _host.AddServiceEndpoint(typeof (IService), binding, address);
ep.Address = new EndpointAddress(address, EndpointIdentity.CreateX509CertificateIdentity(ServiceCert));
_host.Open();
Client side:
var binding = new WSHttpBinding
{
Security =
{
Mode = SecurityMode.Message,
Message =
{
ClientCredentialType = MessageCredentialType.Certificate,
AlgorithmSuite = SecurityAlgorithmSuite.Basic256Sha256Rsa15
}
}
};
var address = new Uri(#"http://serviceaddress");
var endpoint = new EndpointAddress(address, EndpointIdentity.CreateX509CertificateIdentity(ServerCert));
var channelFactory = new ChannelFactory<IService>(binding, endpoint)
{
Credentials =
{
ServiceCertificate =
{
DefaultCertificate = ServerCert,
Authentication =
{
RevocationMode = X509RevocationMode.NoCheck,
TrustedStoreLocation = StoreLocation.LocalMachine,
CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust
}
},
ClientCertificate =
{
Certificate = ClientCert
}
}
};
var channel = channelFactory.CreateChannel();
this msdn article helped tremendously. I think the root of the problem was setting the following message security parameters to false:
httpBinding.Security.Message.NegotiateServiceCredential = false;
httpBinding.Security.Message.EstablishSecurityContext = false;
So now the overall code for the server side looks more like:
var httpBinding = new WSHttpBinding(SecurityMode.Message);
httpBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
httpBinding.Security.Message.NegotiateServiceCredential = false;
httpBinding.Security.Message.EstablishSecurityContext = false;
var httpUri = new Uri("http://serviceaddress");
_host = new ServiceHost(this, httpUri);
_host.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindByThumbprint, serverThumbprint);
_host.Credentials.ClientCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;
_host.Credentials.ClientCertificate.Authentication.TrustedStoreLocation = StoreLocation.LocalMachine;
_host.AddServiceEndpoint(typeof(IMetaService), httpBinding, httpUri);
_host.Open();
and the client side:
var httpBinding = new WSHttpBinding(SecurityMode.Message);
httpBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
httpBinding.Security.Message.NegotiateServiceCredential = false;
httpBinding.Security.Message.EstablishSecurityContext = false;
var httpUri = new Uri("http://serviceaddress");
var httpEndpoint = new EndpointAddress(httpUri, EndpointIdentity.CreateDnsIdentity("name of server cert"));
var newFactory = new ChannelFactory<IMetaService>(httpBinding, httpEndpoint);
newFactory.Credentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindByThumbprint, "client certificate thumbprint");
newFactory.Credentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindByThumbprint, "server certificate thumbprint");
var channel = newFactory.CreateChannel();