C# 协商了哪个TLS版本?
我的应用程序运行在.NET 4.7中。默认情况下,它将尝试使用TLS1.2。 是否可能知道在执行以下HTTP请求时协商了哪个TLS版本C# 协商了哪个TLS版本?,c#,.net,ssl,C#,.net,Ssl,我的应用程序运行在.NET 4.7中。默认情况下,它将尝试使用TLS1.2。 是否可能知道在执行以下HTTP请求时协商了哪个TLS版本 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(decodedUri); if (requestPayload.Length > 0) { using (Stream requestStream = request.GetRequestStream()) {
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(decodedUri);
if (requestPayload.Length > 0)
{
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(requestPayload, 0, requestPayload.Length);
}
}
我只需要这些信息用于日志记录/调试目的,因此在写入请求流或接收响应之前获得这些信息并不重要。我不想为这些信息分析网络跟踪日志,也不想创建第二个连接(使用SslStream或类似的连接)。我唯一能找到的方法是使用
SslStream
建立测试连接,然后检查SslProtocol
属性
TcpClient client = new TcpClient(decodedUri.DnsSafeHost, 443);
SslStream sslStream = new SslStream(client.GetStream());
// use this overload to ensure SslStream has the same scope of enabled protocol as HttpWebRequest
sslStream.AuthenticateAsClient(decodedUri.Host, null,
(SslProtocols)ServicePointManager.SecurityProtocol, true);
// Check sslStream.SslProtocol here
client.Close();
sslStream.Close();
我已经检查过
sslStream.SslProtocol
将始终与HttpWebRequest
的连接所使用的TlsStream.m_worker.SslProtocol
相同您可以使用反射来获取TlsStream->SslState->SslProtocol
属性值。
此信息可以从HttpWebRequest.GetRequestStream()
和HttpWebRequest.GetResponseStream()
返回的流中提取
using System.IO.Compression;
using System.Net;
using System.Net.Security;
using System.Reflection;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
//(...)
// Allow all, to then check what the Handshake will agree upon
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 |
SecurityProtocolType.Tls |
SecurityProtocolType.Tls11 |
SecurityProtocolType.Tls12 |
SecurityProtocolType.Tls13;
// Handle the Server certificate exchange, to inspect the certificates received
ServicePointManager.ServerCertificateValidationCallback += TlsValidationCallback;
Uri requestUri = new Uri("https://somesite.com");
var request = WebRequest.CreateHttp(requestUri);
request.Method = WebRequestMethods.Http.Post;
request.ServicePoint.Expect100Continue = false;
request.AllowAutoRedirect = true;
request.CookieContainer = new CookieContainer();
request.ContentType = "application/x-www-form-urlencoded";
var postdata = Encoding.UTF8.GetBytes("Some postdata here");
request.ContentLength = postdata.Length;
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident / 7.0; rv: 11.0) like Gecko";
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate;q=0.8");
request.Headers.Add(HttpRequestHeader.CacheControl, "no-cache");
using (var requestStream = request.GetRequestStream()) {
//Here the request stream is already validated
SslProtocols sslProtocol = ExtractSslProtocol(requestStream);
if (sslProtocol < SslProtocols.Tls12)
{
// Refuse/close the connection
}
}
//(...)
private SslProtocols ExtractSslProtocol(Stream stream)
{
if (stream is null) return SslProtocols.None;
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
Stream metaStream = stream;
if (stream.GetType().BaseType == typeof(GZipStream)) {
metaStream = (stream as GZipStream).BaseStream;
}
else if (stream.GetType().BaseType == typeof(DeflateStream)) {
metaStream = (stream as DeflateStream).BaseStream;
}
var connection = metaStream.GetType().GetProperty("Connection", bindingFlags).GetValue(metaStream);
if (!(bool)connection.GetType().GetProperty("UsingSecureStream", bindingFlags).GetValue(connection)) {
// Not a Https connection
return SslProtocols.None;
}
var tlsStream = connection.GetType().GetProperty("NetworkStream", bindingFlags).GetValue(connection);
var tlsState = tlsStream.GetType().GetField("m_Worker", bindingFlags).GetValue(tlsStream);
return (SslProtocols)tlsState.GetType().GetProperty("SslProtocol", bindingFlags).GetValue(tlsState);
}
TlsInfo tlsInfo = null;
IPHostEntry dnsHost = await Dns.GetHostEntryAsync(HostURI.Host);
using (TcpClient client = new TcpClient(dnsHost.HostName, 443))
{
using (SslStream sslStream = new SslStream(client.GetStream(), false,
TlsValidationCallback, null))
{
sslstream.AuthenticateAsClient(dnsHost.HostName, null,
(SslProtocols)ServicePointManager.SecurityProtocol, false);
tlsInfo = new TlsInfo(sslStream);
}
}
//The HttpWebRequest goes on from here.
HttpWebRequest httpRequest = WebRequest.CreateHttp(HostURI);
//(...)
ExtractSslProtocol()
还处理激活WebRequest
时返回的压缩GzipStream
或deflatesttream
验证将在ServerCertificateValidationCallback
中进行,当使用request.GetRequestStream()初始化请求时调用该回调
注意:SecurityProtocolType.Tls13
包含在.Net Framework4.8+
和.Net Core3.0+
中
using System.IO.Compression;
using System.Net;
using System.Net.Security;
using System.Reflection;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
//(...)
// Allow all, to then check what the Handshake will agree upon
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 |
SecurityProtocolType.Tls |
SecurityProtocolType.Tls11 |
SecurityProtocolType.Tls12 |
SecurityProtocolType.Tls13;
// Handle the Server certificate exchange, to inspect the certificates received
ServicePointManager.ServerCertificateValidationCallback += TlsValidationCallback;
Uri requestUri = new Uri("https://somesite.com");
var request = WebRequest.CreateHttp(requestUri);
request.Method = WebRequestMethods.Http.Post;
request.ServicePoint.Expect100Continue = false;
request.AllowAutoRedirect = true;
request.CookieContainer = new CookieContainer();
request.ContentType = "application/x-www-form-urlencoded";
var postdata = Encoding.UTF8.GetBytes("Some postdata here");
request.ContentLength = postdata.Length;
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident / 7.0; rv: 11.0) like Gecko";
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate;q=0.8");
request.Headers.Add(HttpRequestHeader.CacheControl, "no-cache");
using (var requestStream = request.GetRequestStream()) {
//Here the request stream is already validated
SslProtocols sslProtocol = ExtractSslProtocol(requestStream);
if (sslProtocol < SslProtocols.Tls12)
{
// Refuse/close the connection
}
}
//(...)
private SslProtocols ExtractSslProtocol(Stream stream)
{
if (stream is null) return SslProtocols.None;
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
Stream metaStream = stream;
if (stream.GetType().BaseType == typeof(GZipStream)) {
metaStream = (stream as GZipStream).BaseStream;
}
else if (stream.GetType().BaseType == typeof(DeflateStream)) {
metaStream = (stream as DeflateStream).BaseStream;
}
var connection = metaStream.GetType().GetProperty("Connection", bindingFlags).GetValue(metaStream);
if (!(bool)connection.GetType().GetProperty("UsingSecureStream", bindingFlags).GetValue(connection)) {
// Not a Https connection
return SslProtocols.None;
}
var tlsStream = connection.GetType().GetProperty("NetworkStream", bindingFlags).GetValue(connection);
var tlsState = tlsStream.GetType().GetField("m_Worker", bindingFlags).GetValue(tlsStream);
return (SslProtocols)tlsState.GetType().GetProperty("SslProtocol", bindingFlags).GetValue(tlsState);
}
TlsInfo tlsInfo = null;
IPHostEntry dnsHost = await Dns.GetHostEntryAsync(HostURI.Host);
using (TcpClient client = new TcpClient(dnsHost.HostName, 443))
{
using (SslStream sslStream = new SslStream(client.GetStream(), false,
TlsValidationCallback, null))
{
sslstream.AuthenticateAsClient(dnsHost.HostName, null,
(SslProtocols)ServicePointManager.SecurityProtocol, false);
tlsInfo = new TlsInfo(sslStream);
}
}
//The HttpWebRequest goes on from here.
HttpWebRequest httpRequest = WebRequest.CreateHttp(HostURI);
//(...)
更新2:
secur32.dll
->QueryContextAttributesW()
方法允许查询初始化流的连接安全上下文
[DllImport("secur32.dll", CharSet = CharSet.Auto, ExactSpelling=true, SetLastError=false)]
private static extern int QueryContextAttributesW(
SSPIHandle contextHandle,
[In] ContextAttribute attribute,
[In] [Out] ref SecPkgContext_ConnectionInfo ConnectionInfo
);
从文档中可以看到,此方法返回一个引用SecPkgContext\u ConnectionInfo
结构的void*缓冲区
:
private struct SecPkgContext_ConnectionInfo
{
public SchProtocols dwProtocol;
public ALG_ID aiCipher;
public int dwCipherStrength;
public ALG_ID aiHash;
public int dwHashStrength;
public ALG_ID aiExch;
public int dwExchStrength;
}
schprotocol
成员是SslProtocol
有什么收获。
引用连接上下文句柄的TlsStream.Context.m\u SecurityContext.\u句柄
不是公共的。
因此,您也只能通过反射或通过TcpClient.GetStream()返回的System.Net.Security.AuthenticatedStream
派生类(System.Net.Security.SslStream
和System.Net.Security.NegotiateStream
)获得它
using System.IO.Compression;
using System.Net;
using System.Net.Security;
using System.Reflection;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
//(...)
// Allow all, to then check what the Handshake will agree upon
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 |
SecurityProtocolType.Tls |
SecurityProtocolType.Tls11 |
SecurityProtocolType.Tls12 |
SecurityProtocolType.Tls13;
// Handle the Server certificate exchange, to inspect the certificates received
ServicePointManager.ServerCertificateValidationCallback += TlsValidationCallback;
Uri requestUri = new Uri("https://somesite.com");
var request = WebRequest.CreateHttp(requestUri);
request.Method = WebRequestMethods.Http.Post;
request.ServicePoint.Expect100Continue = false;
request.AllowAutoRedirect = true;
request.CookieContainer = new CookieContainer();
request.ContentType = "application/x-www-form-urlencoded";
var postdata = Encoding.UTF8.GetBytes("Some postdata here");
request.ContentLength = postdata.Length;
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident / 7.0; rv: 11.0) like Gecko";
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate;q=0.8");
request.Headers.Add(HttpRequestHeader.CacheControl, "no-cache");
using (var requestStream = request.GetRequestStream()) {
//Here the request stream is already validated
SslProtocols sslProtocol = ExtractSslProtocol(requestStream);
if (sslProtocol < SslProtocols.Tls12)
{
// Refuse/close the connection
}
}
//(...)
private SslProtocols ExtractSslProtocol(Stream stream)
{
if (stream is null) return SslProtocols.None;
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
Stream metaStream = stream;
if (stream.GetType().BaseType == typeof(GZipStream)) {
metaStream = (stream as GZipStream).BaseStream;
}
else if (stream.GetType().BaseType == typeof(DeflateStream)) {
metaStream = (stream as DeflateStream).BaseStream;
}
var connection = metaStream.GetType().GetProperty("Connection", bindingFlags).GetValue(metaStream);
if (!(bool)connection.GetType().GetProperty("UsingSecureStream", bindingFlags).GetValue(connection)) {
// Not a Https connection
return SslProtocols.None;
}
var tlsStream = connection.GetType().GetProperty("NetworkStream", bindingFlags).GetValue(connection);
var tlsState = tlsStream.GetType().GetField("m_Worker", bindingFlags).GetValue(tlsStream);
return (SslProtocols)tlsState.GetType().GetProperty("SslProtocol", bindingFlags).GetValue(tlsState);
}
TlsInfo tlsInfo = null;
IPHostEntry dnsHost = await Dns.GetHostEntryAsync(HostURI.Host);
using (TcpClient client = new TcpClient(dnsHost.HostName, 443))
{
using (SslStream sslStream = new SslStream(client.GetStream(), false,
TlsValidationCallback, null))
{
sslstream.AuthenticateAsClient(dnsHost.HostName, null,
(SslProtocols)ServicePointManager.SecurityProtocol, false);
tlsInfo = new TlsInfo(sslStream);
}
}
//The HttpWebRequest goes on from here.
HttpWebRequest httpRequest = WebRequest.CreateHttp(HostURI);
//(...)
不幸的是,WebRequest/WebResponse返回的流不能强制转换到这些类。连接和流类型仅通过非公共属性和字段引用
我正在发布组装好的文档,它可能会帮助您找到另一条通向上下文句柄的路径
声明、结构、枚举器列表位于中
Microsoft TechNet
MSDN
代码库(部分)
更新1:
我在您对另一个答案的评论中看到,该解决方案使用
TcpClient()
不适用于您。反正我要把它留在这里所以
这篇文章中的评论将对其他感兴趣的人有用。另外,3种可能的解决方案比2种要好
提供的上下文中使用的一些实现细节
如果在初始化WebRequest之前需要协议信息,则可以使用TLS连接所需的相同工具在相同上下文中建立TcpClient()连接。即,定义支持的协议和验证服务器证书
TcpClient()和WebRequest都可以使用这些设置:
-启用所有协议,并让TLS握手确定将使用哪一个协议。
-定义一个RemoteCertificateValidationCallback()
委托来验证服务器在X509Chain
中传递的X509Certificates
using System.IO.Compression;
using System.Net;
using System.Net.Security;
using System.Reflection;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
//(...)
// Allow all, to then check what the Handshake will agree upon
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 |
SecurityProtocolType.Tls |
SecurityProtocolType.Tls11 |
SecurityProtocolType.Tls12 |
SecurityProtocolType.Tls13;
// Handle the Server certificate exchange, to inspect the certificates received
ServicePointManager.ServerCertificateValidationCallback += TlsValidationCallback;
Uri requestUri = new Uri("https://somesite.com");
var request = WebRequest.CreateHttp(requestUri);
request.Method = WebRequestMethods.Http.Post;
request.ServicePoint.Expect100Continue = false;
request.AllowAutoRedirect = true;
request.CookieContainer = new CookieContainer();
request.ContentType = "application/x-www-form-urlencoded";
var postdata = Encoding.UTF8.GetBytes("Some postdata here");
request.ContentLength = postdata.Length;
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident / 7.0; rv: 11.0) like Gecko";
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate;q=0.8");
request.Headers.Add(HttpRequestHeader.CacheControl, "no-cache");
using (var requestStream = request.GetRequestStream()) {
//Here the request stream is already validated
SslProtocols sslProtocol = ExtractSslProtocol(requestStream);
if (sslProtocol < SslProtocols.Tls12)
{
// Refuse/close the connection
}
}
//(...)
private SslProtocols ExtractSslProtocol(Stream stream)
{
if (stream is null) return SslProtocols.None;
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
Stream metaStream = stream;
if (stream.GetType().BaseType == typeof(GZipStream)) {
metaStream = (stream as GZipStream).BaseStream;
}
else if (stream.GetType().BaseType == typeof(DeflateStream)) {
metaStream = (stream as DeflateStream).BaseStream;
}
var connection = metaStream.GetType().GetProperty("Connection", bindingFlags).GetValue(metaStream);
if (!(bool)connection.GetType().GetProperty("UsingSecureStream", bindingFlags).GetValue(connection)) {
// Not a Https connection
return SslProtocols.None;
}
var tlsStream = connection.GetType().GetProperty("NetworkStream", bindingFlags).GetValue(connection);
var tlsState = tlsStream.GetType().GetField("m_Worker", bindingFlags).GetValue(tlsStream);
return (SslProtocols)tlsState.GetType().GetProperty("SslProtocol", bindingFlags).GetValue(tlsState);
}
TlsInfo tlsInfo = null;
IPHostEntry dnsHost = await Dns.GetHostEntryAsync(HostURI.Host);
using (TcpClient client = new TcpClient(dnsHost.HostName, 443))
{
using (SslStream sslStream = new SslStream(client.GetStream(), false,
TlsValidationCallback, null))
{
sslstream.AuthenticateAsClient(dnsHost.HostName, null,
(SslProtocols)ServicePointManager.SecurityProtocol, false);
tlsInfo = new TlsInfo(sslStream);
}
}
//The HttpWebRequest goes on from here.
HttpWebRequest httpRequest = WebRequest.CreateHttp(HostURI);
//(...)
实际上,TLS握手在建立TCP客户端或WebRequest连接时是相同的。
这种方法让您知道HttpWebRequest将与同一服务器协商什么Tls协议
设置TcpClient()
以接收和评估SslStream
检查证书职业
标志设置为假
,因此该过程不会浪费时间查找吊销列表。
证书验证回调与ServicePointManager
中指定的相同
using System.IO.Compression;
using System.Net;
using System.Net.Security;
using System.Reflection;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
//(...)
// Allow all, to then check what the Handshake will agree upon
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 |
SecurityProtocolType.Tls |
SecurityProtocolType.Tls11 |
SecurityProtocolType.Tls12 |
SecurityProtocolType.Tls13;
// Handle the Server certificate exchange, to inspect the certificates received
ServicePointManager.ServerCertificateValidationCallback += TlsValidationCallback;
Uri requestUri = new Uri("https://somesite.com");
var request = WebRequest.CreateHttp(requestUri);
request.Method = WebRequestMethods.Http.Post;
request.ServicePoint.Expect100Continue = false;
request.AllowAutoRedirect = true;
request.CookieContainer = new CookieContainer();
request.ContentType = "application/x-www-form-urlencoded";
var postdata = Encoding.UTF8.GetBytes("Some postdata here");
request.ContentLength = postdata.Length;
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident / 7.0; rv: 11.0) like Gecko";
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate;q=0.8");
request.Headers.Add(HttpRequestHeader.CacheControl, "no-cache");
using (var requestStream = request.GetRequestStream()) {
//Here the request stream is already validated
SslProtocols sslProtocol = ExtractSslProtocol(requestStream);
if (sslProtocol < SslProtocols.Tls12)
{
// Refuse/close the connection
}
}
//(...)
private SslProtocols ExtractSslProtocol(Stream stream)
{
if (stream is null) return SslProtocols.None;
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
Stream metaStream = stream;
if (stream.GetType().BaseType == typeof(GZipStream)) {
metaStream = (stream as GZipStream).BaseStream;
}
else if (stream.GetType().BaseType == typeof(DeflateStream)) {
metaStream = (stream as DeflateStream).BaseStream;
}
var connection = metaStream.GetType().GetProperty("Connection", bindingFlags).GetValue(metaStream);
if (!(bool)connection.GetType().GetProperty("UsingSecureStream", bindingFlags).GetValue(connection)) {
// Not a Https connection
return SslProtocols.None;
}
var tlsStream = connection.GetType().GetProperty("NetworkStream", bindingFlags).GetValue(connection);
var tlsState = tlsStream.GetType().GetField("m_Worker", bindingFlags).GetValue(tlsStream);
return (SslProtocols)tlsState.GetType().GetProperty("SslProtocol", bindingFlags).GetValue(tlsState);
}
TlsInfo tlsInfo = null;
IPHostEntry dnsHost = await Dns.GetHostEntryAsync(HostURI.Host);
using (TcpClient client = new TcpClient(dnsHost.HostName, 443))
{
using (SslStream sslStream = new SslStream(client.GetStream(), false,
TlsValidationCallback, null))
{
sslstream.AuthenticateAsClient(dnsHost.HostName, null,
(SslProtocols)ServicePointManager.SecurityProtocol, false);
tlsInfo = new TlsInfo(sslStream);
}
}
//The HttpWebRequest goes on from here.
HttpWebRequest httpRequest = WebRequest.CreateHttp(HostURI);
//(...)
TlsInfo
类收集有关已建立的安全连接的一些信息:
-TLS协议版本
-密码和散列算法
-SSL握手中使用的服务器证书
public class TlsInfo
{
public TlsInfo(SslStream SecureStream)
{
this.ProtocolVersion = SecureStream.SslProtocol;
this.CipherAlgorithm = SecureStream.CipherAlgorithm;
this.HashAlgorithm = SecureStream.HashAlgorithm;
this.RemoteCertificate = SecureStream.RemoteCertificate;
}
public SslProtocols ProtocolVersion { get; set; }
public CipherAlgorithmType CipherAlgorithm { get; set; }
public HashAlgorithmType HashAlgorithm { get; set; }
public X509Certificate RemoteCertificate { get; set; }
}
下面的解决方案无疑是一个“黑客”,因为它确实使用了反射,但它目前涵盖了HttpWebRequest可能遇到的大多数情况。如果无法确定Tls版本,它将返回null。在您将任何内容写入请求流之前,它还会验证同一请求中的Tls版本。如果调用该方法时还没有发生流Tls握手,它将触发该方法
您的示例用法如下所示:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("...");
request.Method = "POST";
if (requestPayload.Length > 0)
{
using (Stream requestStream = request.GetRequestStream())
{
SslProtocols? protocol = GetSslProtocol(requestStream);
requestStream.Write(requestPayload, 0, requestPayload.Length);
}
}
方法是:
public static SslProtocols? GetSslProtocol(Stream stream)
{
if (stream == null)
return null;
if (typeof(SslStream).IsAssignableFrom(stream.GetType()))
{
var ssl = stream as SslStream;
return ssl.SslProtocol;
}
var flags = BindingFlags.NonPublic | BindingFlags.Instance;
if (stream.GetType().FullName == "System.Net.ConnectStream")
{
var connection = stream.GetType().GetProperty("Connection", flags).GetValue(stream);
var netStream = connection.GetType().GetProperty("NetworkStream", flags).GetValue(connection) as Stream;
return GetSslProtocol(netStream);
}
if (stream.GetType().FullName == "System.Net.TlsStream")
{
// type SslState
var ssl = stream.GetType().GetField("m_Worker", flags).GetValue(stream);
if (ssl.GetType().GetProperty("IsAuthenticated", flags).GetValue(ssl) as bool? != true)
{
// we're not authenticated yet. see: https://referencesource.microsoft.com/#System/net/System/Net/_TLSstream.cs,115
var processAuthMethod = stream.GetType().GetMethod("ProcessAuthentication", flags);
processAuthMethod.Invoke(stream, new object[] { null });
}
var protocol = ssl.GetType().GetProperty("SslProtocol", flags).GetValue(ssl) as SslProtocols?;
return protocol;
}
return null;
}
把一些想法放在一起,我做了一个简单的方法来测试每个可用的协议,每次尝试强制一种特定类型的连接。
最后,我会得到一个列表,上面有我需要使用的结果
注:只有当你知道网站在线时,测试才有效-你可以做一个先前的测试来检查这个
public static IEnumerable<T> GetValues<T>()
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
private Dictionary<SecurityProtocolType, bool> ProcessProtocols(string address)
{
var protocolResultList = new Dictionary<SecurityProtocolType, bool>();
var defaultProtocol = ServicePointManager.SecurityProtocol;
ServicePointManager.Expect100Continue = true;
foreach (var protocol in GetValues<SecurityProtocolType>())
{
try
{
ServicePointManager.SecurityProtocol = protocol;
var request = WebRequest.Create(address);
var response = request.GetResponse();
protocolResultList.Add(protocol, true);
}
catch
{
protocolResultList.Add(protocol, false);
}
}
ServicePointManager.SecurityProtocol = defaultProtocol;
return protocolResultList;
}
公共静态IEnumerable GetValues()
{
返回Enum.GetValues(typeof(T)).Cast();
}
专用字典处理程序