我有一个简单的web服务调用,由。net (c#) 2.0 Windows应用程序生成,通过Visual Studio生成的web服务代理,用于同样用c#(2.0)编写的web服务。这种方法已经有效了好几年,并且在十几个正在运行的地方继续有效。
在新地点的新安装遇到了问题。当试图调用web服务时,它失败了,消息说:
无法为SSL/TLS安全建立信任关系
通道
web服务的URL使用SSL (https://)——但这已经在许多其他位置工作了很长时间(并继续这样做)。
我该往哪里看?这可能是Windows和。net之间的安全问题,是此安装独有的吗?如果是,我在哪里建立信任关系?我迷路了!
如果你使用的是Windows 2003,你可以这样做:
Open Microsoft Management Console
(Start --> Run --> mmc.exe);
Choose File --> Add/Remove Snap-in;
In the Standalone tab, choose Add;
Choose the Certificates snap-in, and
click Add;
In the wizard, choose the Computer
Account, and then choose Local
Computer. Press Finish to end the
wizard;
Close the Add/Remove Snap-in dialog;
Navigate to Certificates (Local
Computer) and choose a store to
import:
If you have the Root CA certificate
for the company that issued the
certificate, choose Trusted Root
Certification Authorities;
If you have the certificate for the
server itself, choose Other People
Right-click the store and choose All
Tasks --> Import
Follow the wizard and provide the
certificate file you have;
After that, simply restart IIS and try
calling the web service again.
参考:http://www.outsystems.com/NetworkForums/ViewTopic.aspx?Topic=Web-Services: -Could-not-establish-trust-relationship-for-the-SSL / TLS -…
下面的代码片段将修复您正在调用的服务器上的SSL证书有问题的情况。例如,证书可能是自签名的,或者证书和服务器之间的主机名可能不匹配。
如果您正在调用您直接控制之外的服务器,这是危险的,因为您不能再确定您正在与您认为连接到的服务器通信。但是,如果您处理的是内部服务器,而获得“正确的”证书是不现实的,请使用以下命令告诉web服务忽略证书问题并勇敢地继续工作。
前两个使用lambda表达式,第三个使用常规代码。第一个接受任何证书。后两者至少检查证书中的主机名是否是您所期望的主机名。
... 希望对你有帮助
//Trust all certificates
System.Net.ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) => true);
// trust sender
System.Net.ServicePointManager.ServerCertificateValidationCallback
= ((sender, cert, chain, errors) => cert.Subject.Contains("YourServerName"));
// validate cert by calling a function
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);
// callback used to validate the certificate in an SSL conversation
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
{
bool result = cert.Subject.Contains("YourServerName");
return result;
}
Luke写了一篇关于这方面的好文章。
非常直截了当。试试吧
卢克的解决方案
原因(引用自他的文章(含诅咒))
“. .
上面的代码的问题是,如果您的证书无效,它将无法工作。为什么我要发布到一个网页与无效的SSL证书?因为我很便宜,我不想付钱给Verisign或其他** *的人对我的测试箱进行认证,所以我自己签名了。当我发送请求时,我得到了一个可爱的例外:
System.Net.WebException
底层连接被关闭。无法与远程服务器建立信任关系。
我不知道你怎么想,但对我来说,这个异常看起来像是由我的代码中一个愚蠢的错误引起的,导致POST失败。所以我一直在寻找,调整,做各种奇怪的事情。只有在我谷歌了***n的东西,我发现遇到无效的SSL证书后的默认行为是抛出这个异常。
. .”
如果您不想盲目地信任所有人,只对某些主机设置信任例外,那么下面的解决方案更合适。
public static class Ssl
{
private static readonly string[] TrustedHosts = new[] {
"host1.domain.com",
"host2.domain.com"
};
public static void EnableTrustedHosts()
{
ServicePointManager.ServerCertificateValidationCallback =
(sender, certificate, chain, errors) =>
{
if (errors == SslPolicyErrors.None)
{
return true;
}
var request = sender as HttpWebRequest;
if (request != null)
{
return TrustedHosts.Contains(request.RequestUri.Host);
}
return false;
};
}
}
那就打电话给Ssl。当你的应用启动时启用托管主机。
如果没有工作坏证书,当ServerCertificateValidationCallback返回true;
我的ServerCertificateValidationCallback代码:
ServicePointManager.ServerCertificateValidationCallback += delegate
{
LogWriter.LogInfo("Проверка сертификата отключена, на уровне ServerCertificateValidationCallback");
return true;
};
我的代码被阻止执行ServerCertificateValidationCallback:
if (!(ServicePointManager.CertificatePolicy is CertificateValidation))
{
CertificateValidation certValidate = new CertificateValidation();
certValidate.ValidatingError += new CertificateValidation.ValidateCertificateEventHandler(this.OnValidateCertificateError);
ServicePointManager.CertificatePolicy = certValidate;
}
OnValidateCertificateError功能:
private void OnValidateCertificateError(object sender, CertificateValidationEventArgs e)
{
string msg = string.Format(Strings.OnValidateCertificateError, e.Request.RequestUri, e.Certificate.GetName(), e.Problem, new Win32Exception(e.Problem).Message);
LogWriter.LogError(msg);
//Message.ShowError(msg);
}
我禁用了CertificateValidation代码和ServerCertificateValidationCallback运行得很好
我已经用了一段时间了如果有用的话。
调用方必须显式地请求需要不受信任的认证,并在完成时将回调放回默认状态。
/// <summary>
/// Helper method for returning the content of an external webpage
/// </summary>
/// <param name="url">URL to get</param>
/// <param name="allowUntrustedCertificates">Flags whether to trust untrusted or self-signed certificates</param>
/// <returns>HTML of the webpage</returns>
public static string HttpGet(string url, bool allowUntrustedCertificates = false) {
var oldCallback = ServicePointManager.ServerCertificateValidationCallback;
string webPage = "";
try {
WebRequest req = WebRequest.Create(url);
if (allowUntrustedCertificates) {
// so we can query self-signed certificates
ServicePointManager.ServerCertificateValidationCallback =
((sender, certification, chain, sslPolicyErrors) => true);
}
WebResponse resp = req.GetResponse();
using (StreamReader sr = new StreamReader(resp.GetResponseStream())) {
webPage = sr.ReadToEnd().Trim();
sr.Close();
}
return webPage;
}
catch {
// if the remote site fails to response (or we have no connection)
return null;
}
finally {
ServicePointManager.ServerCertificateValidationCallback = oldCallback;
}
}