System.Net.WebException thrown when consuming a web service over HTTPS
When making a call to a web service running on a server using HTTPS my application throws a System.Net.WebException with the message "The underlying connecti开发者_如何学Goon was closed: Could not establish trust relationship with remote server". I'm not sure how to get around this issue and successfully make the call.
After some research, I found a blog entry by Jan Tielens which explains what is going on and a workaround for my problem:
When you browse to a HTTPS site, you probably get a dialog window asking you if you want to trust the certificate provided by the webserver. So the responsibility of accepting the certificate is handled by the user. Let's get back to the webservice scenario, if you want to invoke a webservice located on a webserver which uses SSL and HTTPS there is a problem. When you make the call from code, there is no dialog window popping up, and asking if you trust the certificate (luckily because this would be pretty ugly in server-side scenarios); probably you'll get following exception:
An unhandled exception of type
System.Net.WebException
occurred in System.dll
Additional information: The underlying connection was closed: Could not establish trust relationship with remote server.But there is a solution for this problem, you can solve this in your code by creating your own
CertificatePolicy
class (which implements theICertificatePolicy
interface). In this class you will have to write your ownCheckValidationResult
function that has to returntrue
orfalse
, like you would press yes or no in the dialog window. For development purposes I've created the following class which accepts all certificates, so you won't get the nastyWebException
anymore:
public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
{
public TrustAllCertificatePolicy() { }
public bool CheckValidationResult(ServicePoint sp, X509Certificate cert, WebRequest req, int problem)
{
return true;
}
}
As you can see the
CheckValidationResult
function always returns true, so all certificates will be trusted. If you want to make this class a little bit more secure, you can add additional checks using theX509Certificate
parameter for example. To use thisCertificatePolicy
, you'll have to tell theServicePointManager
to use it:
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
This must be done (one time during the application life cycle) before making the call to your webservice.
If you're using a self signed SSL cert, or an untrusted SSL cert, you can tell your application to ignore it (If you really want to ignore it). e.g.
ServicePointManager.ServerCertificateValidationCallback = _
new RemoteCertificateValidationCallback(IgnoreSelfSSL)
public bool IgnoreSelfSSL(ServicePoint sp, X509Certificate cert,WebRequest req, int problem) {
return true;
}
You can place the callback anywhere that will be hit prior to executing your service call.
Tips given in answers should be used only for testing. For acceptance/production you should have WS certificate installed on machine making call to WS, and make certificate validation before calling WS - expiration, subject etc. Then you can add this certificate to WS request through SoapHttpClientProtocol.Proxy.ClientCertificates.
精彩评论