单声道https webrequest失败,"验证或解密失败"

Joe*_*oel 67 c# mono https webrequest

我正在制作一个简单的REST客户端,用于我的C#应用​​程序.在Windows上的.net它适用于http://和https://连接.在Ubuntu 10.10的单声道2.6.7(也用2.8测试,结果相同)只有http://有效.https:// connections在request.GetResponse()方法上抛出此异常:

Unhandled Exception: System.Net.WebException: Error getting response stream (Write: The authentication or decryption has failed.): SendFailure ---> System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: Invalid certificate received from server. Error code: 0xffffffff800b010a
  at Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.validateCertificates (Mono.Security.X509.X509CertificateCollection certificates) [0x00000] in <filename unknown>:0 
  at Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.ProcessAsTls1 () [0x00000] in <filename unknown>:0 
  at Mono.Security.Protocol.Tls.Handshake.HandshakeMessage.Process () [0x00000] in <filename unknown>:0 
  at (wrapper remoting-invoke-with-check) Mono.Security.Protocol.Tls.Handshake.HandshakeMessage:Process ()
  at Mono.Security.Protocol.Tls.ClientRecordProtocol.ProcessHandshakeMessage (Mono.Security.Protocol.Tls.TlsStream handMsg) [0x00000] in <filename unknown>:0 
  at Mono.Security.Protocol.Tls.RecordProtocol.InternalReceiveRecordCallback (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0 
  --- End of inner exception stack trace ---
  at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0 
  at System.Net.HttpWebRequest.GetResponse () [0x00000] in <filename unknown>:0 
Run Code Online (Sandbox Code Playgroud)

我一直无法找到解决这个问题的方法.任何人都知道为什么会这样,以及如何解决它?

同样,这只在Mono中失败,.Net似乎没有任何建立连接的问题.

这是调用代码:

public JToken DoRequest(string path, params string[] parameters) {
    if(!path.StartsWith("/")) {
        path = "/" + path;
    }
    string fullUrl = url + path + ToQueryString(parameters);

    if(DebugUrls) Console.WriteLine("Requesting: {0}", fullUrl);

    WebRequest request = HttpWebRequest.CreateDefault(new Uri(fullUrl));
    using(WebResponse response = request.GetResponse())
    using(Stream responseStream = response.GetResponseStream()) {
        return ReadResponse(responseStream);
    }
}
Run Code Online (Sandbox Code Playgroud)

Lud*_*ltz 48

我有同样的问题Unity(也使用单声道),这篇文章帮我解决了.

只需在提出请求之前添加以下行:

ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;
Run Code Online (Sandbox Code Playgroud)

而这种方法:

public bool MyRemoteCertificateValidationCallback(System.Object sender,
    X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    bool isOk = true;
    // If there are errors in the certificate chain,
    // look at each error to determine the cause.
    if (sslPolicyErrors != SslPolicyErrors.None) {
        for (int i=0; i<chain.ChainStatus.Length; i++) {
            if (chain.ChainStatus[i].Status == X509ChainStatusFlags.RevocationStatusUnknown) {
                continue;
            }
            chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
            chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
            chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan (0, 1, 0);
            chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
            bool chainIsValid = chain.Build ((X509Certificate2)certificate);
            if (!chainIsValid) {
                isOk = false;
                break;
            }
        }
    }
    return isOk;
}
Run Code Online (Sandbox Code Playgroud)

  • 像魅力一样工作.(Y) (3认同)
  • 抱歉,您的解决方案是使用网上找到的_random code_滚动您自己的SSL证书验证_?如果您不关心SSL所提供的安全性,只需将函数return true即可。这只是“用力挥舞的安全性”,而且确实完全被破坏了,并且很乐意接受被破坏或欺骗的证书。 (3认同)

sco*_*732 28

Windows上的.NET Framework使用Windows证书存储(mmc,添加/删除管理单元,证书)来确定是否接受来自远程站点的SSL证书.Windows附带了许多根证书和中间证书颁发机构(CA),它们会定期由Windows Update更新.因此,您的.NET代码通常会信任证书,前提是证书由证书存储区中的CA或CA的后代颁发(包括大多数信誉良好的商业CA).

在Mono中,没有Windows证书存储区.Mono拥有自己的商店.默认情况下,它为空(没有可信的默认CA).您需要自己管理条目.

看看这里:

mozroots.exe点将使您的单声道安装信任Firefox在默认安装后信任的所有内容.


Paw*_*iya 7

在发出请求http请求之前写下这一行.这应该是有效的.

ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback((sender, certificate, chain, policyErrors) => { return true; });


private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        //Return true if the server certificate is ok
        if (sslPolicyErrors == SslPolicyErrors.None)
            return true;

        bool acceptCertificate = true;
        string msg = "The server could not be validated for the following reason(s):\r\n";

        //The server did not present a certificate
        if ((sslPolicyErrors &
             SslPolicyErrors.RemoteCertificateNotAvailable) == SslPolicyErrors.RemoteCertificateNotAvailable)
        {
            msg = msg + "\r\n    -The server did not present a certificate.\r\n";
            acceptCertificate = false;
        }
        else
        {
            //The certificate does not match the server name
            if ((sslPolicyErrors &
                 SslPolicyErrors.RemoteCertificateNameMismatch) == SslPolicyErrors.RemoteCertificateNameMismatch)
            {
                msg = msg + "\r\n    -The certificate name does not match the authenticated name.\r\n";
                acceptCertificate = false;
            }

            //There is some other problem with the certificate
            if ((sslPolicyErrors &
                 SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.RemoteCertificateChainErrors)
            {
                foreach (X509ChainStatus item in chain.ChainStatus)
                {
                    if (item.Status != X509ChainStatusFlags.RevocationStatusUnknown &&
                        item.Status != X509ChainStatusFlags.OfflineRevocation)
                        break;

                    if (item.Status != X509ChainStatusFlags.NoError)
                    {
                        msg = msg + "\r\n    -" + item.StatusInformation;
                        acceptCertificate = false;
                    }
                }
            }
        }

        //If Validation failed, present message box
        if (acceptCertificate == false)
        {
            msg = msg + "\r\nDo you wish to override the security check?";
//          if (MessageBox.Show(msg, "Security Alert: Server could not be validated",
//                       MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1) == DialogResult.Yes)
                acceptCertificate = true;
        }

        return acceptCertificate;
    }
Run Code Online (Sandbox Code Playgroud)

  • 请考虑包含有关您的答案的一些信息,而不是简单地发布代码.我们不仅尝试提供"修复",还帮助人们学习.您应该解释原始代码中的错误,您的不同之处,以及您的更改的工作原因. (7认同)
  • 这与合理的网络安全性相反:您只是在没有首先验证证书的情况下接受任何证书.请参阅@Ludovic的答案,了解在接受之前验证的功能. (4认同)
  • 这会拒绝 SSL 错误的子类,但会静默允许其他错误(例如自签名证书)。因此(就像这里的其他答案一样),这有效地禁用了 SSL 的所有安全优势。如果这就是你想要的,只需`return true;`。 (2认同)

小智 5

Mono默认情况下不信任任何证书,要导入Mozilla受信任的根权限,您可以mozroots --import --quiet在mozroots.exe所在的mono安装文件夹中运行