在最新更新的 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();
}
}
结束。
输了你,赢了世界又如何...
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
2013-08-09 sliverlight资源文件的URI调用
2013-08-09 使用SQL语句的子查询批量复制表数据
2013-08-09 javascript页面刷新的一些方法
2013-08-09 使用Frame控件设计Silverlight的导航