.NET Core中SQL Server连接字符串设encrypt=strict引发超时错误
问题描述
我正在开发基于.NET Core 6.0的Blazor应用,原本使用连接字符串:
Data Source=MySource;Initial Catalog=MyDb;Integrated Security=SSPI;encrypt=true;TrustServerCertificate=True
可正常连接兼容级别为2016的SQL Server 2016数据库。由于使用的是Microsoft.Data.SqlClient 5.1.0,我希望启用TDS增强安全特性。按照文档指引,我将连接字符串中的encrypt值改为encrypt=strict,但调用connection.Open()时出现如下错误:
Microsoft.Data.SqlClient.SqlException HResult=0x80131904 Message=The client was unable to establish a connection because of an error during connection initialization process before login. Possible causes include the following: the client tried to connect to an unsupported version of SQL Server; the server was too busy to accept new connections; or there was a resource limitation (insufficient memory or maximum allowed connections) on the server. (provider: SSL Provider, error: 0 - The wait operation timed out.) Source=Core Microsoft SqlClient Data Provider StackTrace: at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at Microsoft.Data.SqlClient.TdsParser.EnableSsl(UInt32 info, SqlConnectionEncryptOption encrypt, Boolean integratedSecurity, String serverCertificateFilename) at Microsoft.Data.SqlClient.TdsParser.SendPreLoginHandshake(Byte[] instanceName, SqlConnectionEncryptOption encrypt, Boolean integratedSecurity, String serverCertificateFilename) at Microsoft.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, SqlConnectionString connectionOptions, Boolean withFailover) at Microsoft.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, Boolean withFailover) at Microsoft.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout) at Microsoft.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance) at Microsoft.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, Boolean applyTransientFaultHandling, String accessToken, DbConnectionPool pool) at Microsoft.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions) at Microsoft.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions) at Microsoft.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) at Microsoft.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides) at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides) Inner Exception 1: Win32Exception: The wait operation timed out.
请问这是否与我的SQL Server版本有关?
答案
是的,这个错误确实和你的SQL Server版本直接相关。
TDS 8.0增强安全特性要求SQL Server支持TLS 1.2或更高版本的加密协议,并且服务器必须拥有由受信任证书颁发机构(CA)签署的有效SSL证书。而SQL Server 2016本身虽然支持TLS 1.2,但encrypt=strict模式对服务器的证书验证有更严格的要求:
- 它不允许使用
TrustServerCertificate=True来跳过证书验证(你的原始连接字符串中使用了这个参数),必须验证服务器证书的有效性和信任链。 - 另外,SQL Server 2016的默认配置可能没有启用符合
strict模式要求的加密设置,或者服务器证书不符合标准(比如自签名证书在strict模式下会被拒绝)。
当你设置encrypt=strict后,客户端会强制要求服务器提供完整可信的证书链,同时使用TLS 1.2+加密。如果SQL Server 2016的证书不满足要求,或者服务器未正确配置TLS 1.2及以上协议,就会导致连接超时或失败。
建议你:
- 检查SQL Server 2016是否已启用TLS 1.2,且服务器证书是由受信任CA颁发的有效证书(不能是自签名证书)。
- 如果无法更换证书,
encrypt=strict模式并不适用于SQL Server 2016,建议继续使用encrypt=true并配合TrustServerCertificate=True(仅在测试或内部环境使用),或者升级到SQL Server 2019及以上版本以完全支持TDS 8.0的严格加密模式。
内容的提问来源于stack exchange,提问作者user8149311
相关产品推荐
相关产品推荐

