I'm trying to call a C# dll from classic ASP - this dll calls a webservice. I've been asked by someone that runs that ASP site to create this dll for him and had tons of problems doing that. He told me he has a *.crt file, and that the dll should use that to call his SSL-based webservice.
So since this is classic ASP, had to make it a COM object and also configure the service and endpoint through code, like so:
BasicHttpBinding binding = new BasicHttpBinding();
binding.Name = "Service1Binding";
binding.CloseTimeout = System.TimeSpan.Parse("00:01:00");
binding.OpenTimeout = System.TimeSpan.Parse("00:01:00");
binding.ReceiveTimeout = System.TimeSpan.Parse("00:10:00");
binding.SendTimeout = System.TimeSpan.Parse("00:01:00");
binding.AllowCookies = false;
binding.BypassProxyOnLocal = false;
binding.HostNameComparisonMode = System.ServiceModel.HostNameComparisonMode.StrongWildcard;
binding.MaxBufferSize = 65536;
binding.MaxBufferPoolSize = 524288;
binding.MaxReceivedMessageSize = 65536;
binding.MessageEncoding = System.ServiceModel.WSMessageEncoding.Text;
binding.TextEncoding = System.Text.Encoding.UTF8;
binding.TransferMode = System.ServiceModel.TransferMode.Buffered;
binding.UseDefaultWebProxy = true;
binding.ReaderQuotas.MaxDepth = 32;
binding.ReaderQuotas.MaxStringContentLength = 8192;
binding.ReaderQuotas.MaxArrayLength = 16384;
binding.ReaderQuotas.MaxBytesPerRead = 4096;
binding.ReaderQuotas.MaxNameTableCharCount = 16384;
binding.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.None;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
binding.Security.Transport.Realm = "";
binding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;
binding.Security.Message.AlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Default;
EndpointAddress endpoint =
new EndpointAddress("https://webservice.XXXX.com/Service1.svc");
var cert = new X509Certificate2(certPath); //local path to *.crt file
Service1.ServiceClient client = new Service1.ServiceClient(binding, endpoint);
client.ClientCredentials.ClientCertificate.Certificate = cert;
var result = client.HelloWorld();
At first i got a Forbidden exception, so I changed the Security.Mode to be BasicHttpSecurityMode.TransportWithMessageCredential. Now, I'm getting this error:
The private key is not present in the X.509 certificate
Is it looking for the cert in the store, or using the path I gave it? How can i make this work?
Related
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;
}
Our environment is based on server application which exposes service through WCF. Out customer uses a load balancer - F5. Client application hits it through secured channel and later it uses non-secured HTTP channel. Both client and server uses WsHttpBinding.
Client <> HTTPS <> F5 <> HTTP <> Server
I managed to work with such configuration, but our service uses custom authorization based on JWT tokens and then problem occurs.
I've tested many configurations, but there were various errors.
Currently configuration of client:
var binding = new WSHttpBinding();
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.NegotiateServiceCredential = true;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
Server configuration looks like:
var binding = new WSHttpBinding();
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
host.Description.Behaviors.Find<ServiceBehaviorAttribute>().AddressFilterMode = AddressFilterMode.Any;
binding.Security.Mode = SecurityMode.None;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.NegotiateServiceCredential = true;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
host.Description.Behaviors.Find<ServiceAuthorizationBehavior>().ServiceAuthorizationManager = new JWTAuthorizationManager();
Client application sets authorization headers in such way:
channelFactory.Credentials.UserName.UserName = userId;
credentialBehaviour.UserName.Password = token;
Current status is that request goes to the service, but in CheckAccess() method from JWTAuthorizationManager HttpRequestHeader.Authorization is empty. Moreover System.ServiceModel.MustUnderstandSoapException is thrown. When I switched Security.Mode of client to Transport same thing happens but exception isn't thrown.
I'm not familiar with the details of this technology and I'm not sure what really happens.
UPDATE:
I've checked what is received by service. I see that Security header exists in the message, but service can't interpret this because of Security Mode set to None. I can't set this to Message because it requires certificate on the server machine, we don't want this.
I managed with this problem using CustomBinding at the server side:
var binding = new CustomBinding();
var securityHeader = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
securityHeader.AllowInsecureTransport = true;
securityHeader.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;
securityHeader.SecurityHeaderLayout = SecurityHeaderLayout.Strict;
securityHeader.IncludeTimestamp = true;
var textEncoding = new TextMessageEncodingBindingElement();
textEncoding.MessageVersion = MessageVersion.Soap12WSAddressing10;
binding.Elements.Add(textEncoding);
var httpTransport = new HttpTransportBindingElement();
httpTransport.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
httpTransport.MaxReceivedMessageSize = int.MaxValue;
httpTransport.MaxBufferPoolSize = int.MaxValue;
binding.Elements.Add(httpTransport);
I have the following code which was validation using username & password.
How can I use Windows credentials instead?
private static SecurityToken GetClaims(string serviceurl, string username, string password)
{
bool isincurrentusercontext = String.IsNullOrEmpty(username);
WS2007HttpBinding binding = new WS2007HttpBinding();
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Message.EstablishSecurityContext = false;
EndpointAddress endpoint = new EndpointAddress(new Uri(GetStsUrl(isincurrentusercontext)));
WSTrustChannelFactory trustChannelFactory;
if (!isincurrentusercontext)
{
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
trustChannelFactory = new WSTrustChannelFactory(binding, endpoint);
trustChannelFactory.Credentials.UserName.UserName = username;
trustChannelFactory.Credentials.UserName.Password = password;
}
else
trustChannelFactory = new WSTrustChannelFactory(new KerberosWSTrustBinding(SecurityMode.TransportWithMessageCredential), endpoint);
trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;
trustChannelFactory.Credentials.UseIdentityConfiguration = true;
WSTrustChannel channel = null;
RequestSecurityToken rst = new RequestSecurityToken(RequestTypes.Issue);
rst.AppliesTo = new EndpointReference(serviceurl);
rst.KeyType = KeyTypes.Bearer;
channel = (WSTrustChannel)trustChannelFactory.CreateChannel();
SecurityToken token = channel.Issue(rst);
((IChannel)channel).Close();
channel = null;
trustChannelFactory.Close();
trustChannelFactory = null;
return token;
}
If I change,
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
to
binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
and remove these two statements,
trustChannelFactory.Credentials.UserName.UserName = username;
trustChannelFactory.Credentials.UserName.Password = password;
and when i run this statement,
SecurityToken token = channel.Issue(rst);
I get the following error,
Secure channel cannot be opened because security negotiation with the
remote endpoint has failed. This may be due to absent or incorrectly
specified EndpointIdentity in the EndpointAddress used to create the
channel. Please verify the EndpointIdentity specified or implied by
the EndpointAddress correctly identifies the remote endpoint
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;
I have implemented a scenario which uses netTcpBinding and WsHttpBinding with Transport Security(https) as communication binding type in WCF. Then I compared the performance results. Interestingly, netTcpBinding was slower than wsHttpBinding. I have read a a lot of documents about binding performance and I know that the netTcpBinding provides the fastest communication because of binary encoding.
Can you explain what may cause this situation in my tests? Thanks.
Test environment: IIS 7
public static WSHttpBinding GetWSHttpForSSLBinding()
{
WSHttpBinding binding = new WSHttpBinding();
binding.TransactionFlow = true;
binding.MaxReceivedMessageSize = 2147483647;
binding.MessageEncoding = WSMessageEncoding.Text;
binding.Security.Mode = SecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.ReaderQuotas.MaxStringContentLength = 2147483647;
binding.OpenTimeout = TimeSpan.MaxValue;
binding.CloseTimeout = TimeSpan.MaxValue;
binding.SendTimeout = TimeSpan.MaxValue;
binding.ReceiveTimeout = TimeSpan.MaxValue;
return binding;
}
public static NetTcpBinding GetTcpBinding()
{
NetTcpBinding binding = new NetTcpBinding();
binding.TransactionFlow = true;
binding.MaxReceivedMessageSize = 2147483647;
binding.PortSharingEnabled = true;
binding.Security.Mode = SecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
binding.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;
binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
binding.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.TripleDesSha256;
binding.ReaderQuotas.MaxStringContentLength = 2147483647;
binding.ReaderQuotas.MaxArrayLength = 2147483647;
binding.OpenTimeout = TimeSpan.MaxValue;
binding.CloseTimeout = TimeSpan.MaxValue;
binding.SendTimeout = TimeSpan.MaxValue;
binding.ReceiveTimeout = TimeSpan.MaxValue;
return binding;
}
Your net.tcp binding uses authentication but ws http binding doesn't. Alse repeat your test with several operation calls from single proxy and with bigger message load. First call is always slow because of channel creation and connection establishment.
Are you talking about latency or throughput. Does a client create a connection and then immediately close it or does it span over multiple calls.
NetTcp has optimization over a same connection and payload size would be smaller since it uses BinaryEncoding vs TextEncoding for wshttp.
If you are looking at latency - NetTcp does windows auth with causes an AD lookup vs on wshttp you are using SSL auth.