尽管连接字符串中有 TrustServerCertificate=true,但 SSL / 证书验证错误
SSL / certificate validation error in spite of TrustServerCertificate=true in connection string
首先请注意,我知道这个问题已经被问过好几次了。但是,到目前为止给出的已接受(和未接受)的解决方案不适用于我的情况,因此从那时起一定发生了实质性的变化,希望有理由再次询问。
话虽如此:
我目前正在尝试将 Access 2010 .adp 应用程序升级到 Access 2019 .accdb。该应用程序包含大量 VBA 代码,这些代码使用 ADO 对象连接并在 Microsoft SQL 服务器(当前:2008 R2,但将很快升级)上运行。
我想保留大部分代码,这意味着坚持使用 ADO,所以要走的路是新的 OleDB SQL 服务器驱动程序(在2018)。 SQL 服务器在我的客户端应用程序之外的另一台机器上运行。
我无法从 VBA 建立到 SQL 服务器的连接。执行以下代码片段时
Dim cnTemp As Connection
Set cnTemp = New Connection
cnTemp.CursorLocation = adUseServer
cntemp.Open "Provider=MSOLEDBSQL;Server=dbserver.example.com;Initial Catalog=MyDB;Authentication=SqlPassword;User ID=sa;Password=secret;DataTypeCompatibility=80;"
执行最后一行时出现以下错误:
SSL Provider: The certificate chain was issued by an authority which is not trusted.
好的,没问题,毕竟我们已经找到了处理同一问题的所有其他问题,所有这些问题都提出了相同的解决方案:将 Trust Server Certificate=True;
添加到连接字符串。
好吧,试过了,但令我惊讶的是,情况还是一样。然后我尝试了一些其他变体,如 TrustServerCertificate=True;
或使用 true
而不是 True
,但无济于事。我还尝试添加 Use Encryption for Data=True;
但这也没有帮助(这是可以预料的)。此外,我尝试了一些在研究问题时发现的片段,但 Microsoft 未将其记录为在 ADO 连接字符串中有效(如 Encrypt=true
或 Trusted_Connection=true;
);当然,这使情况变得更糟,引发了其他错误消息。
我明白我可以通过将 SQL 服务器证书放入客户端的受信任的根证书库,或者让 SQL 服务器使用由已知的、受信任的 CA(例如 Let's Encrypt)。
但是,我非常想知道为什么将 Trust Server Certificate=true;
添加到我的连接字符串不会使错误消失,以及我必须在其中放置什么来禁用证书验证(顺便说一句,如果我们不开始讨论为什么这会很糟糕,我将不胜感激;这只是在受信任的封闭网络中进行开发和测试,我知道可能存在的风险)。
连接字符串中的 TrustServerCertificate=True
不被接受的原因有两个。一是它不是有效的 ADO 经典 (ADODB) 连接字符串关键字。根据ActiveX Data Objects (ADO) Connection String Keywords documentation,keyword/value对应该是Trust Server Certificate=True
(注意空格)。关键字在没有空格的情况下被完全忽略,因此不被信任。
但是,由于 Authentication-SqlPassword
规范,仅此更改不会信任证书。当指定 Authentication
关键字时,文档脚注会调用:
To improve security, encryption and certificate validation behavior is
modified when using Authentication/Access Token initialization
properties or their corresponding connection string keywords. For details, see Encryption and certificate validation link.
引用的 link 包含以下重要说明:
Certificate validation can also be controlled through the Value field
of the
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\SNI18.0\GeneralFlags\Flag2
registry entry. Valid values are 0 or 1. The OLE DB driver chooses the
most secure option between the registry and the connection
property/keyword settings. That is, the driver will validate the
server certificate as long as at least one of the registry/connection
settings enables server certificate validation.
因此,即使使用 Trust Server Certificate=True
,当此注册表值设置为 0 时,证书也会被验证。
一个解决方案是简单地删除 Authentication=SqlPassword
规范,只要您不需要通过不信任服务器证书来提高安全性:
cntemp.Open "Provider=MSOLEDBSQL;Server=dbserver.example.com;Initial Catalog=MyDB;User ID=sa;Password=secret;Trust Server Certificate=True;DataTypeCompatibility=80;"
首先,我想声明所有功劳归功于@Dan Guzman。是他的回答/评论提供了解决方案。
但是,我想根据发布问题后所做的研究添加一些背景知识。
问题是微软的文档明显有误。请查看以下文档:
位于SQL Server 2017 -> OLE DB -> Applications -> Using connection string keywords with OLE DB Driver for SQL server
版块,应该是正确的。它分为三个部分;在这个问题的上下文中,最后一个 table 是我们感兴趣的,因为只有这个与 ADO 的连接字符串有关。
最后的 table 明确表明 Authentication=SqlPawword
在 ADO / OLE DB 连接字符串中有效(重新格式化我的,内容没有改变):
Authentication SSPROP_AUTH_MODE Specifies the SQL or Active
Directory authentication used. Valid values are:
(not set)
: Authentication mode determined by other keywords.
ActiveDirectoryPassword
: Active Directory authentication using login ID and password.
ActiveDirectoryIntegrated
: Integrated authentication to Active Directory using the currently logged-in user's Windows account
credentials.
NOTE: It's recommended that applications using Integrated Security (or Trusted_Connection) authentication keywords or their corresponding
properties set the value of the Authentication keyword (or its
corresponding property) to ActiveDirectoryIntegrated to enable new
encryption and certificate validation behavior.
SqlPassword
: Authentication using login ID and password.
NOTE: It's recommended that applications using SQL Server authentication set the value of the Authentication keyword (or its
corresponding property) to SqlPassword to enable new encryption and
certificate validation behavior.
它还说(同样,格式化我的,内容没有改变):
Trust Server Certificate SSPROP_INIT_TRUST_SERVER_CERTIFICATE
Accepts the strings "true" and "false" as values. The default value
is "false", which means that the server certificate will be validated.
每个通情达理的人都会理解这一点,因为 Trust Server Certificate=true
将禁用证书验证。
但是当你看到这里时
您会注意到此文档的结构与第一个文档类似,最后一个 table 没有 提及 Authentication
参数。
但是,此文档位于 SQL Server 2017 -> Development -> SQL Server Native Client -> Applications -> Using Connection String Keywords
。这意味着它与我们的案例无关,因为它涉及 SQL 服务器本机客户端(而不是 OLE DB),但它提供了正确的信息。
所以我们有提供错误信息的正确文档和提供正确信息的不相关文档。恭喜你,微软,你又让我浪费了一整天...
此外,我还找到了以下文档:
阅读标题("Using Azure Active Directory"),它应该仅与 Azure 有关。但是,我怀疑以下部分也与本地 SQL 服务器安装有关(格式化我的,内容未更改):
Certificate validation
To improve security, the new connection properties/keywords respect
the TrustServerCertificate setting (and its corresponding connection
string keywords/properties) independently of the client encryption
setting. As a result, server certificate is validated by default.
Note
Certificate validation can also be controlled through the Value field
of the
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\SNI18.0\GeneralFlags\Flag2
registry entry. Valid values are 0 or 1. The OLE DB driver chooses the
most secure option between the registry and the connection
property/keyword settings. That is, the driver will validate the
server certificate as long as at least one of the registry/connection
settings enables server certificate validation.
因此很可能我们还必须更改注册表中的值以在通过 ADO / OLE DB 连接到 SQL 服务器时最终禁用证书验证。
首先请注意,我知道这个问题已经被问过好几次了。但是,到目前为止给出的已接受(和未接受)的解决方案不适用于我的情况,因此从那时起一定发生了实质性的变化,希望有理由再次询问。
话虽如此:
我目前正在尝试将 Access 2010 .adp 应用程序升级到 Access 2019 .accdb。该应用程序包含大量 VBA 代码,这些代码使用 ADO 对象连接并在 Microsoft SQL 服务器(当前:2008 R2,但将很快升级)上运行。
我想保留大部分代码,这意味着坚持使用 ADO,所以要走的路是新的 OleDB SQL 服务器驱动程序(在2018)。 SQL 服务器在我的客户端应用程序之外的另一台机器上运行。
我无法从 VBA 建立到 SQL 服务器的连接。执行以下代码片段时
Dim cnTemp As Connection
Set cnTemp = New Connection
cnTemp.CursorLocation = adUseServer
cntemp.Open "Provider=MSOLEDBSQL;Server=dbserver.example.com;Initial Catalog=MyDB;Authentication=SqlPassword;User ID=sa;Password=secret;DataTypeCompatibility=80;"
执行最后一行时出现以下错误:
SSL Provider: The certificate chain was issued by an authority which is not trusted.
好的,没问题,毕竟我们已经找到了处理同一问题的所有其他问题,所有这些问题都提出了相同的解决方案:将 Trust Server Certificate=True;
添加到连接字符串。
好吧,试过了,但令我惊讶的是,情况还是一样。然后我尝试了一些其他变体,如 TrustServerCertificate=True;
或使用 true
而不是 True
,但无济于事。我还尝试添加 Use Encryption for Data=True;
但这也没有帮助(这是可以预料的)。此外,我尝试了一些在研究问题时发现的片段,但 Microsoft 未将其记录为在 ADO 连接字符串中有效(如 Encrypt=true
或 Trusted_Connection=true;
);当然,这使情况变得更糟,引发了其他错误消息。
我明白我可以通过将 SQL 服务器证书放入客户端的受信任的根证书库,或者让 SQL 服务器使用由已知的、受信任的 CA(例如 Let's Encrypt)。
但是,我非常想知道为什么将 Trust Server Certificate=true;
添加到我的连接字符串不会使错误消失,以及我必须在其中放置什么来禁用证书验证(顺便说一句,如果我们不开始讨论为什么这会很糟糕,我将不胜感激;这只是在受信任的封闭网络中进行开发和测试,我知道可能存在的风险)。
连接字符串中的 TrustServerCertificate=True
不被接受的原因有两个。一是它不是有效的 ADO 经典 (ADODB) 连接字符串关键字。根据ActiveX Data Objects (ADO) Connection String Keywords documentation,keyword/value对应该是Trust Server Certificate=True
(注意空格)。关键字在没有空格的情况下被完全忽略,因此不被信任。
但是,由于 Authentication-SqlPassword
规范,仅此更改不会信任证书。当指定 Authentication
关键字时,文档脚注会调用:
To improve security, encryption and certificate validation behavior is modified when using Authentication/Access Token initialization properties or their corresponding connection string keywords. For details, see Encryption and certificate validation link.
引用的 link 包含以下重要说明:
Certificate validation can also be controlled through the Value field of the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\SNI18.0\GeneralFlags\Flag2 registry entry. Valid values are 0 or 1. The OLE DB driver chooses the most secure option between the registry and the connection property/keyword settings. That is, the driver will validate the server certificate as long as at least one of the registry/connection settings enables server certificate validation.
因此,即使使用 Trust Server Certificate=True
,当此注册表值设置为 0 时,证书也会被验证。
一个解决方案是简单地删除 Authentication=SqlPassword
规范,只要您不需要通过不信任服务器证书来提高安全性:
cntemp.Open "Provider=MSOLEDBSQL;Server=dbserver.example.com;Initial Catalog=MyDB;User ID=sa;Password=secret;Trust Server Certificate=True;DataTypeCompatibility=80;"
首先,我想声明所有功劳归功于@Dan Guzman。是他的回答/评论提供了解决方案。
但是,我想根据发布问题后所做的研究添加一些背景知识。
问题是微软的文档明显有误。请查看以下文档:
位于SQL Server 2017 -> OLE DB -> Applications -> Using connection string keywords with OLE DB Driver for SQL server
版块,应该是正确的。它分为三个部分;在这个问题的上下文中,最后一个 table 是我们感兴趣的,因为只有这个与 ADO 的连接字符串有关。
最后的 table 明确表明 Authentication=SqlPawword
在 ADO / OLE DB 连接字符串中有效(重新格式化我的,内容没有改变):
Authentication SSPROP_AUTH_MODE Specifies the SQL or Active Directory authentication used. Valid values are:
(not set)
: Authentication mode determined by other keywords.ActiveDirectoryPassword
: Active Directory authentication using login ID and password.
ActiveDirectoryIntegrated
: Integrated authentication to Active Directory using the currently logged-in user's Windows account credentials.NOTE: It's recommended that applications using Integrated Security (or Trusted_Connection) authentication keywords or their corresponding properties set the value of the Authentication keyword (or its corresponding property) to ActiveDirectoryIntegrated to enable new encryption and certificate validation behavior.
SqlPassword
: Authentication using login ID and password.NOTE: It's recommended that applications using SQL Server authentication set the value of the Authentication keyword (or its corresponding property) to SqlPassword to enable new encryption and certificate validation behavior.
它还说(同样,格式化我的,内容没有改变):
Trust Server Certificate SSPROP_INIT_TRUST_SERVER_CERTIFICATE Accepts the strings "true" and "false" as values. The default value is "false", which means that the server certificate will be validated.
每个通情达理的人都会理解这一点,因为 Trust Server Certificate=true
将禁用证书验证。
但是当你看到这里时
您会注意到此文档的结构与第一个文档类似,最后一个 table 没有 提及 Authentication
参数。
但是,此文档位于 SQL Server 2017 -> Development -> SQL Server Native Client -> Applications -> Using Connection String Keywords
。这意味着它与我们的案例无关,因为它涉及 SQL 服务器本机客户端(而不是 OLE DB),但它提供了正确的信息。
所以我们有提供错误信息的正确文档和提供正确信息的不相关文档。恭喜你,微软,你又让我浪费了一整天...
此外,我还找到了以下文档:
阅读标题("Using Azure Active Directory"),它应该仅与 Azure 有关。但是,我怀疑以下部分也与本地 SQL 服务器安装有关(格式化我的,内容未更改):
Certificate validation
To improve security, the new connection properties/keywords respect the TrustServerCertificate setting (and its corresponding connection string keywords/properties) independently of the client encryption setting. As a result, server certificate is validated by default.
Note
Certificate validation can also be controlled through the Value field of the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\SNI18.0\GeneralFlags\Flag2 registry entry. Valid values are 0 or 1. The OLE DB driver chooses the most secure option between the registry and the connection property/keyword settings. That is, the driver will validate the server certificate as long as at least one of the registry/connection settings enables server certificate validation.
因此很可能我们还必须更改注册表中的值以在通过 ADO / OLE DB 连接到 SQL 服务器时最终禁用证书验证。