Ian*_*oyd 4 sql-server encryption sql-server-2008-r2
Provider=SQLOLEDB;Data Source=hydrogen;User ID=lgilmore;Password=squeegebeckenheim;Use Encryption for Data=true;Trust Server Certificate=true;给出错误:
[DBNETLIB][ConnectionOpen (SECDoClientHandshake()).]SSL 安全错误
我正在尝试加密 SQL Server 和 OLEDB 客户端(例如 ADO、SQLOLEDB)之间的通信。
我们从 Microsoft 注意到(除非您自己配置了一个),SQL Server 会自动生成一个自签名证书,用于保护登录过程:
使用加密而不验证
SQL Server 始终对与登录相关的网络数据包进行加密。如果服务器启动时未配置证书,SQL Server 会生成一个自签名证书,用于加密登录数据包。
我们的客户可以要求我们始终使用加密——而不仅仅是在登录过程中。再次,来自微软:
应用程序还可以使用连接字符串关键字或连接属性请求对所有网络流量进行加密。关键词是:
"Encrypt":对于 ODBC 和 OLE DB,当将提供程序字符串与IDbInitialize::Initialize一起使用时,或者"Use Encryption for Data"对于 ADO 和 OLE DB,将初始化字符串与IDataInitialize一起使用时。
这个Use Encryption for Data连接字符串关键字意味着我们要使用:
SQL Server 自动生成的自签名证书是自签名的。通常,客户端驱动程序会遍历证书的信任链以查看证书是否有效。使用自动自签名证书连接将失败。
但是还有另一个关键字可以强制客户端接受服务器证书:信任服务器证书:
为了在服务器上未配置证书时启用加密,应用程序可以使用
"TrustServerCertificate"关键字或其关联的连接属性来保证进行加密。为了即使在未配置服务器证书的情况下也能保证加密,应用程序可能会请求加密和"TrustServerCertificate".当
Trust Server Certificate设置为 true 时,传输层将使用 SSL 加密通道并绕过证书链来验证信任。
所以我们有两个关键词:
Use Encryption for Data=true:选择加密Trust Server Certificate=true:信任自签名证书现在来一些最低限度可重现的代码。
SqlClient即我没有使用ADO.NET)为了进一步说明我正在使用 OLEDB,我将给出一个直接使用 OLEDB 的代码示例(尽管这对于 ADO 来说都是正确的;它只是 OLDB 的一个薄包装):
String connectionString =
"Provider=SQLOLEDB;Data Source=hydrogen;"+
"User ID=lgilmore;Password=squeegebeckenheim;";
//DAInitialize helper class parses the connection string
IDataInitialize dataInit = (IDataInitialize)CreateComObject(CLSID_MSDAInitialize);
//Ask DAInitialize to create the SQLOLEDB class for us and set it up
IDBInitialize dataSource;
dataInit.GetDataSource(null, CLSCTX_INPROC_SERVER, connectionString, IDBInitialize, ref (IUnknown)dataSource);
//Connect to SQL Server
dataSource.Initialize(); //actually opens the database connection
Run Code Online (Sandbox Code Playgroud)
我们的初始代码示例尚未请求加密;所以我们能够建立联系也就不足为奇了。与 SQL Server 的连接已顺利建立。(我们可以使用 SQL Profiler 确认连接)。
我们将代码重构为接受连接字符串的函数:
String connectionString =
"Provider=SQLOLEDB;Data Source=hydrogen;"+
"User ID=lgilmore;Password=squeegebeckenheim;"+
"Use Encryption for Data=true"; //opt-in to encryption of data
IDbInitialize dataSource = ConnectToDataSource(connectionString);
Run Code Online (Sandbox Code Playgroud)
使用我们的新辅助函数:
IDbInitialize ConnectToDataSource(String connectionString)
{
//DAInitialize helper class parses the connection string
IDataInitialize dataInit = (IDataInitialize)CreateComObject(CLSID_MSDAInitialize);
//Ask DAInitialize to create the SQLOLEDB class for us and set it up
IDBInitialize dataSource;
dataInit.GetDataSource(null, CLSCTX_INPROC_SERVER, connectionString, IDBInitialize, ref (IUnknown)dataSource);
//Connect to SQL Server
dataSource.Initialize(); //actually opens the database connection
}
Run Code Online (Sandbox Code Playgroud)
我们预计此代码在连接到数据库时会失败。它确实:
[DBNETLIB][ConnectionOpen (SECDoClientHandshake()).]SSL 安全错误
我们现在将连接字符串更新为Trust Server Certificate=true:
String connectionString =
"Provider=SQLOLEDB;Data Source=hydrogen;"+
"User ID=lgilmore;Password=squeegebeckenheim;"+
"Use Encryption for Data=true;"+ //opt-into encryption of data
"Trust Server Certificate=true"; //trust the self-signed server cert
Run Code Online (Sandbox Code Playgroud)
但它仍然失败并出现相同的错误:
[DBNETLIB][ConnectionOpen (SECDoClientHandshake()).]SSL 安全错误
如何指定存在很多混乱Trust Server Certificate。在直接初始化 OLEDB 提供程序、使用IDataInitializeSQL Server Native Client (SQLNCLI)、ADO.net SqlClient和 Java ODBC 之间,存在一些变体:
Trust Server Certificate=trueTrust Server Certificate=yesTrustServerCertificate=trueTrustServerCertificate=yes我尝试了上述所有四种变体;但没有一个起作用。
我使用了该类DataLinks来规范化我的连接字符串:
String CanonicalizeConnectionString(String cs)
{
IDataInitialize dataInit = (IDataInitialize)CreateComObject(CLSID_DataLinks);
IDBInitialize datasource;
dataInit.GetDataSource(nil, CLSCTX_INPROC_SERVER, connectionString, IDBInitialize, ref (IUnknown)dataSource);
String result;
dataInit.GetInitializationString(dataSource, true, out result);
return result;
}
Run Code Online (Sandbox Code Playgroud)
这给了我原始的和解析后的连接字符串:
Provider=SQLOLEDB;Data Source=hydrogen;User ID=lgilmore;Password=squeegebeckenheim;Use Encryption for Data=true;Trust Server Certificate=true;Provider=SQLOLEDB.1;Password=squeegebeckenheim;User ID=lgilmore;Data Source=hydrogen;Extended Properties="Trust Server Certificate=true";Use Encryption for Data=True鉴于Trust Server Certificate已将其放入无法识别的属性的包罗万象中:
Extended Properties="Trust Server Certificate=true"它未被识别的事实意味着我可能必须继续寻找正确的神奇语法。
我想到了。
向数据源询问它支持的所有属性:
String EnumerateAllProperties(String connectionString)
{
IDataInitialize dataInit = (IDataInitialize)CreateComObject(CLSID_MSDAInitialize);
IDBInitialize dataSource;
dataInit.GetDataSource(null, CLSCTX_INPROC_SERVER, connectionString, IDBInitialize, ref (IUnknown)dataSource);
String s = "";
Int32 nSets;
PDBPropInfoSet pi;
POleStr desc;
(dataSource as IDBProperties).GetPropertyInfo(0, null, ref nSets, out pi, ref desc);
for (int i=0, i <nSets, i++)
{
s = s+CRLF+
PropSetGuidToStr(pi.guidPropertySet);
for (int j=0, j < pi[i].cPropertyInfos, j++)
{
s = s+CRLF+
IntToStr(pi[i].rgPropertyInfos[j].dwPropertyID)+TAB+
PWideChar(pi[i].rgPropertyInfos[j].pwszDescription)+TAB+
VTypeToStr(pi[i].rgPropertyInfos[j].vtType);
}
s = s+CRLF;
}
return s;
}
Run Code Online (Sandbox Code Playgroud)
我意识到 SQLOLEDB(Microsoft OLE DB Provider for SQL Server)不支持Trust Server Certificate:
SQLOLEDB -DBPROPSET_DBINIT属性集
| 属性ID | 描述 | 类型 | SQLOLEDB |
|---|---|---|---|
| 7 | 综合安全 | VT_BSTR | 是的 |
| 9 | 密码 | VT_BSTR | 是的 |
| 11 | 保留安全信息 | VT_布尔 | 是的 |
| 12 | 用户身份 | VT_BSTR | 是的 |
| 59 | 数据源 | VT_BSTR | 是的 |
| 60 | 窗把手 | VT_I4 | 是的 |
| 64 | 迅速的 | VT_I2 | 是的 |
| 66 | 连接超时 | VT_I4 | 是的 |
| 160 | 扩展属性 | VT_BSTR | 是的 |
| 186 | 区域设置标识符 | VT_I4 | 是的 |
| 233 | 初始目录 | VT_BSTR | 是的 |
| 248 | OLE DB 服务 | VT_I4 | 是的 |
| 第284章 | 一般超时 | VT_I4 | 是的 |
SQLOLEDB -DBPROPSET_SQLSERVERDBINIT属性集
| 属性ID | 描述 | 类型 | SQLOLEDB |
|---|---|---|---|
| 4 | 当前语言 | VT_BSTR | 是的 |
| 5 | 网络地址 | VT_BSTR | 是的 |
| 6 | 网络图书馆 | VT_BSTR | 是的 |
| 7 | 使用准备程序 | VT_I4 | 是的 |
| 8 | 自动翻译 | VT_布尔 | 是的 |
| 9 | 数据包大小 | VT_I4 | 是的 |
| 10 | 应用名称 | VT_BSTR | 是的 |
| 11 | 工作站ID | VT_BSTR | 是的 |
| 12 | 初始文件名 | VT_BSTR | 是的 |
| 13 | 对数据使用加密 | VT_布尔 | 是的 |
| 14 | 复制服务器名称连接选项 | VT_BSTR | 是的 |
| 15 | 尽可能使用列排序规则标记 | VT_布尔 | 是的 |
如果将其与SQL Server Native Client 11.0进行比较
SQL Server 本机客户端 11.0
SQLNCLI11 -DBPROPSET_DBINIT属性集
| 属性ID | 描述 | 类型 | SQLOLEDB | SQLNCLI11 |
|---|---|---|---|---|
| 7 | 综合安全 | VT_BSTR | 是的 | 是的 |
| 9 | 密码 | VT_BSTR | 是的 | 是的 |
| 11 | 保留安全信息 | VT_布尔 | 是的 | 是的 |
| 12 | 用户身份 | VT_BSTR | 是的 | 是的 |
| 59 | 数据源 | VT_BSTR | 是的 | 是的 |
| 60 | 窗把手 | VT_I4 | 是的 | 是的 |
| 64 | 迅速的 | VT_I2 | 是的 | 是的 |
| 66 | 连接超时 | VT_I4 | 是的 | 是的 |
| 160 | 扩展属性 | VT_BSTR | 是的 | 是的 |
| 186 | 区域设置标识符 | VT_I4 | 是的 | 是的 |
| 200 | 异步处理 | VT_I4 | 不 | 是的 |
| 233 | 初始目录 | VT_BSTR | 是的 | 是的 |
| 248 | OLE DB 服务 | VT_I4 | 是的 | 是的 |
| 第284章 | 一般超时 | VT_I4 | 是的 | 是的 |
SQLNCLI11 -DBPROPSET_SQLSERVERDBINIT属性集
| 属性ID | 描述 | 类型 | SQLOLEDB | SQLNCLI11 |
|---|---|---|---|---|
| 4 | 当前语言 | VT_BSTR | 是的 | 是的 |
| 5 | 网络地址 | VT_BSTR | 是的 | 是的 |
| 6 | 网络图书馆 | VT_BSTR | 是的 | 是的 |
| 7 | 使用准备程序 | VT_I4 | 是的 | 是的 |
| 8 | 自动翻译 | VT_布尔 | 是的 | 是的 |
| 9 | 数据包大小 | VT_I4 | 是的 | 是的 |
| 10 | 应用名称 | VT_BSTR | 是的 | 是的 |
| 11 | 工作站ID | VT_BSTR | 是的 | 是的 |
| 12 | 初始文件名 | VT_BSTR | 是的 | 是的 |
| 13 | 对数据使用加密 | VT_布尔 | 是的 | 是的 |
| 14 | 复制服务器名称连接选项 | VT_BSTR | 是的 | 是的 |
| 15 | 尽可能使用列排序规则标记 | VT_布尔 | 是的 | 是的 |
| 16 | 火星连接 | VT_布尔 | 不 | 是的 |
| 18 | 故障转移合作伙伴 | VT_BSTR | 不 | 是的 |
| 19 | 旧密码 | VT_BSTR | 不 | 是的 |
| 20 | 数据类型兼容性 | VT_UI2 | 不 | 是的 |
| 21 | 信任服务器证书 | VT_布尔 | 不 | 是的 |
| 22 | 服务器SPN | VT_BSTR | 不 | 是的 |
| 23 | 故障转移合作伙伴 SPN | VT_BSTR | 不 | 是的 |
| 24 | 申请意向 | VT_BSTR | 不 | 是的 |
您可以看到已弃用的本机客户端支持Trust Server Certificate,而受支持的OLE DB 客户端则不支持:
| 21 | Trust Server Certificate | VT_BOOL | No | Yes |
Run Code Online (Sandbox Code Playgroud)
考虑到ODBC 驱动程序中的“无法修复”错误(1、2、3 ),这是不幸的
| 归档时间: |
|
| 查看次数: |
5529 次 |
| 最近记录: |