在最新更新的 Windows 系统中使用 .net 程序调用一些 https 接口时出现错误:请求被中止: 未能创建 SSL/TLS 安全通道

这是因为出于安全原因,新更新的系统中会默认禁用一些已经过时不安全的加密协议

如:SSL 3.0、TLS 1.0、TLS 1.1 等

但并不是所有接口服务器都已经更新支持了更新的协议

所以在确认安全的情况下,可以将这些旧的协议再次启用,以达到兼容旧接口调用的目的

方法1:

注意:这个修改会在系统全局范围内影响生效,所以需要考虑影响范围

打开“Internet 选项”控制面板,找到“高级”选项卡

将“安全”结点下的“使用 SSL 3.0”、“使用 TLS 1.0” 等项目勾选上

确定保存后重启系统即可

方法2:

注意:这个修改会在 .net 程序中全局生效,不影响系统其它应用程序,但因为是显式指定,如果加密协议后续有增加,也需要在此同样进行手动增加

在 .net 程序项目中,在调用接口之前,全局指定所需要使用的加密协议:

// 指定请求可使用的加密协议,如果不知道当前项目是因为哪个版本出了问题,可以考虑都加上
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.SystemDefault | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;

请根据实际情况进行配置

参考:https://www.cnblogs.com/Can-daydayup/p/14609089.html

https://learn.microsoft.com/zh-cn/dotnet/api/system.net.securityprotocoltype

方法3:

在低版本的 .NET Framework 中(版本在 4.7 以前),貌似方法1的修改并不会影响方法2

程序默认为 Ssl3、Tls,如果想在不修改程序的情况下修改此默认配置,则需要修改注册表:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

修改后,在最新的系统上,程序默认配置会变更为:Tls、Tls11、Tls12、Tls13

注意:修改后需要重启应用程序生效。

参考:https://stackoverflow.com/questions/28286086/default-securityprotocol-in-net-4-5

更多默认信息:https://blogs.perficient.com/2016/04/28/tls-1-2-and-net-support/

附:参考代码 - 修改注册表(需要重启生效)

public static class SecurityProtocolHelper
{
	public static bool RegistryKeyExists(RegistryHive hive, string subKey, string valueName)
	{
		using (RegistryKey baseKey = RegistryKey.OpenBaseKey(hive, RegistryView.Registry64))
		{
			using (RegistryKey key = baseKey.OpenSubKey(subKey))
			{
				return key != null && key.GetValue(valueName) != null;
			}
		}
	}

	public static void WriteRegistryValue(RegistryHive hive, string subKey, string name, object value)
	{
		using (RegistryKey baseKey = RegistryKey.OpenBaseKey(hive, RegistryView.Registry64))
		{
			using (RegistryKey key = baseKey.CreateSubKey(subKey))
			{
				key.SetValue(name, value);
			}
		}
	}

	public static void DeleteRegistryValue(RegistryHive hive, string subKey, string name)
	{
		using (RegistryKey baseKey = RegistryKey.OpenBaseKey(hive, RegistryView.Registry64))
		{
			using (RegistryKey key = baseKey.CreateSubKey(subKey))
			{
				key.DeleteValue(name);
			}
		}
	}

	public static void SetSecurityProtocol()
	{
		Console.WriteLine("默认的安全协议:" + ServicePointManager.SecurityProtocol);
		Console.WriteLine();

		// 在代码中指定(仅影响运行程序)
		ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
		
		Console.WriteLine("当前的安全协议:" + ServicePointManager.SecurityProtocol);
		Console.WriteLine();
	}

	public static void WriteRegistry()
	{
		Console.WriteLine("默认的安全协议:" + ServicePointManager.SecurityProtocol);
		Console.WriteLine();

		// 修改注册表使用强安全协议(影响所有相同版本的 .NET 程序,需要重启后才能生效)
		string registryPath32Bit = @"SOFTWARE\Microsoft\.NETFramework\v4.0.30319";
		string registryPath64Bit = @"SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319";
		string valueName = "SchUseStrongCrypto";

		if (!RegistryKeyExists(RegistryHive.LocalMachine, registryPath32Bit, valueName))
		{
			// 写入 32 位注册表
			WriteRegistryValue(RegistryHive.LocalMachine, registryPath32Bit, valueName, 1);
		}

		if (!RegistryKeyExists(RegistryHive.LocalMachine, registryPath64Bit, valueName))
		{
			// 写入 64 位注册表
			WriteRegistryValue(RegistryHive.LocalMachine, registryPath64Bit, valueName, 1);
		}

		Console.WriteLine("当前的安全协议:" + ServicePointManager.SecurityProtocol);
		Console.WriteLine();
	}

	public static void DeleteRegistry()
	{
		Console.WriteLine("默认的安全协议:" + ServicePointManager.SecurityProtocol);
		Console.WriteLine();

		// 移除注册表使用强安全协议(影响所有相同版本的 .NET 程序,需要重启后才能生效)
		string registryPath32Bit = @"SOFTWARE\Microsoft\.NETFramework\v4.0.30319";
		string registryPath64Bit = @"SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319";
		string valueName = "SchUseStrongCrypto";

		if (RegistryKeyExists(RegistryHive.LocalMachine, registryPath32Bit, valueName))
		{
			// 写入 32 位注册表
			DeleteRegistryValue(RegistryHive.LocalMachine, registryPath32Bit, valueName);
		}

		if (RegistryKeyExists(RegistryHive.LocalMachine, registryPath64Bit, valueName))
		{
			// 写入 64 位注册表
			DeleteRegistryValue(RegistryHive.LocalMachine, registryPath64Bit, valueName);
		}

		Console.WriteLine("当前的安全协议:" + ServicePointManager.SecurityProtocol);
		Console.WriteLine();
	}
}

结束。

posted @ 2023-08-09 10:10  不是豆豆  阅读(619)  评论(0编辑  收藏  举报
友情链接:迷途