在 C# 中,可以使用 HttpWebRequest 类来获取 HTTPS 网页内容。需要注意的是,HTTPS 网页采用了 SSL/TLS 加密传输机制,必须在发送请求之前获取服务器端的证书并进行验证才能成功获取网页内容。下面是一份示例代码,演示如何获取 HTTPS 网页内容:
using System;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
class Program
{
static void Main(string[] args)
{
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
string url = "https://example.com";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.ProtocolVersion = HttpVersion.Version11;
request.AllowAutoRedirect = true;
request.ContentType = "application/x-www-form-urlencoded";
request.CookieContainer = new CookieContainer();
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
Stream stream = response.GetResponseStream();
string html = string.Empty;
using (StreamReader reader = new StreamReader(stream))
{
html = reader.ReadToEnd();
Console.WriteLine(html);
}
}
}
private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
return true; //如果不希望验证证书有效性,直接返回 true
}
}
在上述代码中,我们首先设置了 ServicePointManager.ServerCertificateValidationCallback 回调函数,该回调函数会在服务器端的证书被验证的时候被调用,当回调函数返回 true 时,表示服务器端的证书验证通过,否则会抛出一个 SSL 异常。接下来,我们创建了一个 HttpWebRequest 构造函数,指定了要获取的 HTTPS 网页的 URL 地址,并设置了一些请求头参数。最后,我们在获取到响应流之后,读取响应流内容,并输出到控制台上。
在实际应用过程中,为了提高安全性,我们应该对服务器端证书进行验证,保证访问的网站是我们信任的网站,防止遭受网络攻击。关于验证服务器端证书需要注意以下几点:如果服务器端证书的颁发机构是受信任的颁发机构,验证可以简化为检查证书的原始日期和过期日期是否合法。你可以使用 certificate.GetExpirationDateString() 和 certificate.GetEffectiveDateString() 函数分别获取证书的原始日期和过期日期,再使用 DateTime.Parse() 函数将其转换为 DateTime 类型。
如果服务器端证书的颁发机构是自签署的或不受信任的颁发机构,那么你需要通过比较证书中的公钥和期望值来验证证书的有效性。你可以使用 certificate.GetPublicKeyString() 函数获取证书的公钥,然后与你预期的公钥进行比较。
如果你希望进一步加强服务器端证书的验证,可以通过检查证书的完整性、状态、可用性等等。可以通过 ChainPolicy() 函数来实现。
以下是一个示例,演示如何通过 ChainPolicy() 函数进行服务器端证书的验证:
private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
if (errors == SslPolicyErrors.None)
{
return true; //如果没有 SSL 错误,直接返回 true
}
Console.WriteLine("Certificate error: {0}", errors);
// 如果是自签名证书,则直接忽略错误
if (errors == SslPolicyErrors.RemoteCertificateChainErrors && chain.ChainStatus.Length == 1)
{
X509ChainStatus chainStatus = chain.ChainStatus[0];
if (chainStatus.Status == X509ChainStatusFlags.UntrustedRoot || chainStatus.Status == X509ChainStatusFlags.PartialChain)
{
return true;
}
}
// 验证服务器端证书的完整性、状态、可用性等等
X509ChainPolicy chainPolicy = new X509ChainPolicy();
chainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
chainPolicy.RevocationMode = X509RevocationMode.Offline;
chainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
chainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
chain.ChainPolicy = chainPolicy;
bool isChainValid = chain.Build((X509Certificate2)certificate);
if (!isChainValid)
{
Console.WriteLine("Chain validation failed!");
foreach (X509ChainStatus chainStatus in chain.ChainStatus)
{
Console.WriteLine("ChainStatus: {0} - {1}", chainStatus.Status, chainStatus.StatusInformation);
}
return false;
}
return true;
}