可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
We are unable to connect to an HTTPS server using WebRequest
because of this error message:
The request was aborted: Could not create SSL/TLS secure channel.
We know that the server doesn't have a valid HTTPS certificate with the path used, but to bypass this issue, we use the following code that we've taken from another StackOverflow post:
private void Somewhere() { ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(AlwaysGoodCertificate); } private static bool AlwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) { return true; }
The problem is that server never validates the certificate and fails with the above error. Does anyone have any idea of what should I do?
I should mention that a colleague and I performed tests a few weeks ago and it was working fine with something similar to what I wrote above. The only "major difference" we've found is that I'm using Windows 7 and he was using Windows XP. Does that change something?
回答1:
I finally found the answer (I haven't noted my source but it was from a search);
While the code works in Windows XP, in Windows 7, you must add this at the beginning:
ServicePointManager.Expect100Continue = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // Use SecurityProtocolType.Ssl3 if needed for compatibility reasons
And now, it works perfectly.
ADDENDUM
As mentioned by Robin French; PayPal no longer support SSL3 so you'll need to use TLS1.2. Paypal Info Page
回答2:
The problem you're having is that the aspNet user doesn't have access to the certificate. You have to give access using the winhttpcertcfg.exe
An example on how to set this up is at: http://support.microsoft.com/kb/901183
Under step 2 in more information
EDIT: In more recent versions of IIS, this feature is built in to the certificate manager tool - and can be accessed by right clicking on the certificate and using the option for managing private keys. More details here: https://serverfault.com/questions/131046/how-to-grant-iis-7-5-access-to-a-certificate-in-certificate-store/132791#132791
回答3:
The error is generic and there are many reasons why the SSL/TLS negotiation may fail. The most common is an invalid or expired server certificate, and you took care of that by providing your own server certificate validation hook, but is not necessarily the only reason. The server may require mutual authentication, it may be configured with a suites of ciphers not supported by your client, it may have a time drift too big for the handshake to succeed and many more reasons.
The best solution is to use the SChannel troubleshooting tools set. SChannel is the SSPI provider responsible for SSL and TLS and your client will use it for the handshake. Take a look at TLS/SSL Tools and Settings.
Also see How to enable Schannel event logging.
回答4:
I had this problem trying to hit https://ct.mob0.com/Styles/Fun.png, which is an image distributed by CloudFlare on it's CDN that supports crazy stuff like SPDY and weird redirect SSL certs.
Instead of specifying Ssl3 as in Simons answer I was able to fix it by going down to Tls12 like this:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; new WebClient().DownloadData("https://ct.mob0.com/Styles/Fun.png");
回答5:
Another possibility is improper certificate importation on the box. Make sure to select encircled check box. Initially I didn't do it, so code was either timing out or throwing same exception as private key could not be located.
回答6:
After many long hours with this same issue I found that the ASP.NET account the client service was running under didn't have access to the certificate. I fixed it by going into the IIS Application Pool that the web app runs under, going into Advanced Settings, and changing the Identity to the LocalSystem
account from NetworkService
.
A better solution is to get the certificate working with the default NetworkService
account but this works for quick functional testing.
回答7:
Something the original answer didn't have. I added some more code to make it bullet proof.
ServicePointManager.Expect100Continue = true; ServicePointManager.DefaultConnectionLimit = 9999; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
回答8:
As you can tell there are plenty of reasons this might happen. Thought I would add the cause I encountered ...
If you set the value of WebRequest.Timeout
to 0
, this is the exception that is thrown. Below is the code I had... (Except instead of a hard-coded 0
for the timeout value, I had a parameter which was inadvertently set to 0
).
WebRequest webRequest = WebRequest.Create(@"https://myservice/path"); webRequest.ContentType = "text/html"; webRequest.Method = "POST"; string body = "..."; byte[] bytes = Encoding.ASCII.GetBytes(body); webRequest.ContentLength = bytes.Length; var os = webRequest.GetRequestStream(); os.Write(bytes, 0, bytes.Length); os.Close(); webRequest.Timeout = 0; //setting the timeout to 0 causes the request to fail WebResponse webResponse = webRequest.GetResponse(); //Exception thrown here ...
回答9:
The "The request was aborted: Could not create SSL/TLS secure channel" exception can occur if the server is returning an HTTP 401 Unauthorized response to the HTTP request.
You can determine if this is happening by turning on trace-level System.Net logging for your client application, as described in this answer.
Once that logging configuration is in place, run the application and reproduce the error, then look in the logging output for a line like this:
System.Net Information: 0 : [9840] Connection#62912200 - Received status line: Version=1.1, StatusCode=401, StatusDescription=Unauthorized.
In my situation, I was failing to set a particular cookie that the server was expecting, leading to the server responding to the request with the 401 error, which in turn led to the "Could not create SSL/TLS secure channel" exception.
回答10:
I have struggled with this problem all day.
When I created a new project with .NET 4.5 I finally got it to work.
But if I downgraded to 4.0 I got the same problem again, and it was irreversable for that project (even when i tried to upgrade to 4.5 again).
Strange no other error message but "The request was aborted: Could not create SSL/TLS secure channel." came up for this error
回答11:
The root of this exception in my case was that at some point in code the following was being called:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
This is really bad. Not only is it instructing .NET to use an insecure protocol, but this impacts every new WebClient (and similar) request made afterward within your appdomain. (Note that incoming web requests are unaffected in your ASP.NET app, but new WebClient requests, such as to talk to an external web service, are).
In my case, it was not actually needed, so I could just delete the statement and all my other web requests started working fine again. Based on my reading elsewhere, I learned a few things:
- This is a global setting in your appdomain, and if you have concurrent activity, you can't reliably set it to one value, do your action, and then set it back. Another action may take place during that small window and be impacted.
- The correct setting is to leave it default. This allows .NET to continue to use whatever is the most secure default value as time goes on and you upgrade frameworks. Setting it to TLS12 (which is the most secure as of this writing) will work now but in 5 years may start causing mysterious problems.
- If you really need to set a value, you should consider doing it in a separate specialized application or appdomain and find a way to talk between it and your main pool. Because it's a single global value, trying to manage it within a busy app pool will only lead to trouble. This answer: https://stackoverflow.com/a/26754917/7656 provides a possible solution by way of a custom proxy. (Note I have not personally implemented it.)
回答12:
In case that the client is a windows machine, a possible reason could be that the tls or ssl protocol required by the service is not activated.
This can be set in:
Control Panel -> Network and Internet -> Internet Options -> Advanced
Scroll settings down to "Security" and choose between
- Use SSL 2.0
- Use SSL 3.0
- Use TLS 1.0
- Use TLS 1.1
- Use TLS 1.2
回答13:
This one is working for me in MVC webclient
public string DownloadSite(string RefinedLink) { try { Uri address = new Uri(RefinedLink); ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; using (WebClient webClient = new WebClient()) { var stream = webClient.OpenRead(address); using (StreamReader sr = new StreamReader(stream)) { var page = sr.ReadToEnd(); return page; } } } catch (Exception e) { log.Error("DownloadSite - error Lin = " + RefinedLink, e); return null; } }
回答14:
Another possible cause of the The request was aborted: Could not create SSL/TLS secure channel
error is a mismatch between your client PC's configured cipher_suites values, and the values that the server is configured as being willing and able to accept. In this case, when your client sends the list of cipher_suites values that it is able to accept in its initial SSL handshaking/negotiation "Client Hello" message, the server sees that none of the provided values are acceptable, and may return an "Alert" response instead of proceeding to the "Server Hello" step of the SSL handshake.
To investigate this possibility, you can download Microsoft Message Analyzer, and use it to run a trace on the SSL negotiation that occurs when you try and fail to establish an HTTPS connection to the server (in your C# app).
If you are able to make a successful HTTPS connection from another environment (e.g. the Windows XP machine that you mentioned -- or possibly by hitting the HTTPS URL in a non-Microsoft browser that doesn't use the OS's cipher suite settings, such as Chrome or Firefox), run another Message Analyzer trace in that environment to capture what happens when the SSL negotiation succeeds.
Hopefully, you'll see some difference between the two Client Hello messages that will allow you to pinpoint exactly what about the failing SSL negotiation is causing it to fail. Then you should be able to make configuration changes to Windows that will allow it to succeed. IISCrypto is a great tool to use for this (even for client PCs, despite the "IIS" name).
The following two Windows registry keys govern the cipher_suites values that your PC will use:
- HKLM\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002
- HKLM\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Local\SSL\00010002
Here's a full writeup of how I investigated and solved an instance of this variety of the Could not create SSL/TLS secure channel
problem: http://blog.jonschneider.com/2016/08/fix-ssl-handshaking-error-in-windows.html
回答15:
I had this problem because my web.config had:
and not:
回答16:
The solution to this, in .NET 4.5 is
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
If you don’t have .NET 4.5 then use
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
回答17:
You can try to install a demo certificate (some ssl providers offers them for free for a month) to be sure if the problem is related to cert validity or not.
回答18:
As long as this is a relatively "live" link I thought I would add a new option. That possibility is that the service is no longer supporting SSL 3.0 due to the problem with the Poodle attack. Check out the Google statement on this. I encountered this problem with several web services at once and realized something had to be going on. I switched to TLS 1.2 and everything is working again.
http://googleonlinesecurity.blogspot.com/2014/10/this-poodle-bites-exploiting-ssl-30.html
回答19:
The issue for me was that I was trying to deploy on IIS as a web service, I installed the certificate on the server, but the user that runs IIS didn't have the correct permissions on the certificate.
How to give ASP.NET access to a private key in a certificate in the certificate store?
回答20:
This was happening for me on just one site, and it turns out that it only had the RC4 cipher available. In a prior effort to harden the server, I had disabled the RC4 cipher, once I re-enabled this the issue was solved.
回答21:
In addition to the answers above, make sure you have imported the CER cert, and NOT the PFX file into your local machine store. A common mistake when you have both files.
回答22:
In my case I had this problem when a Windows service tried to connected to a web service. Looking in Windows events finally I found a error code.
Event ID 36888 (Schannel) is raised:
The following fatal alert was generated: 40. The internal error state is 808.
Finally it was related with a Windows Hotfix. In my case: KB3172605 and KB3177186
The proposed solution in vmware forum was add a registry entry in windows. After adding the following registry all works fine.
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman]
"ClientMinKeyBitLength"=dword:00000200
Apparently it's related with a missing value in the https handshake in the client side.
List your Windows HotFix:
wmic qfe list
Solution Thread:
https://communities.vmware.com/message/2604912#2604912
Hope it's helps.
回答23:
In my case, the service account running the application did not have permission to access the private key. Once I gave this permission, the error went away
- mmc
- certificates
- Expand to personal
- select cert
- right click
- All tasks
- Manage private keys
- Add
回答24:
The default .NET ServicePointManager.SecurityProtocol
uses SSLv3 and TLS. If you are accessing an Apache server, there is a config variable called SSLProtocol
which defaults to TLSv1.2. You can either set the ServicePointManager.SecurityProtocol
to use the appropriate protocol supported by your web server or change your Apache config to allow all protocols like this SSLProtocol
all
.
回答25:
If you are running your code from Visual Studio, try running Visual Studio as administrator. Fixed the issue for me.