连接SQL Server报错

将框架从.NET6升级到8,顺便将各种依赖包也升级,容器化部署到测试环境后,SQL Server连接不了了:

[2024-05-13 13:48:10 ERR] [Microsoft.EntityFrameworkCore.Database.Connection] An error occurred using the connection to database 'Demo' on server '127.0.0.1'. 
[2024-05-13 13:48:10 ERR] [Microsoft.EntityFrameworkCore.Query] An exception occurred while iterating over the results of a query for context type 'DemoDbContext'.
Microsoft.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 31 - Encryption(ssl/tls) handshake failed)
 ---> System.IO.IOException: Received an unexpected EOF or 0 bytes from the transport stream.

以前也遇到过类似的问题,是通过修改TLS的最低支持版本来解决,但这次是升级了依赖导致的无法连接数据库,之前的解决方式不起作用,说明对这个问题的理解还不到位。

在github上提了个issue,原来是在EFCore 7这个版本有个breaking change:连接字符串中的Encrypt参数的默认值有False变为了True,那么在连接数据库时就会尝试建立加密连接,也就是这个过程失败了。

Encrypt=False,若SQL Server配置了强制使用加密连接也会去尝试建立加密连接

失败原因是SQL Server的证书没有在客户端通过校验。下面是本机进行复现的错误信息:

 

那么解决方案有以下几种:

  • 给SQL Server安装正确的证书

  • 在连接字符串中添加TrustServerCertificate=True

  • 连接字符串中设置Encrypt=False

后面两种比较简单,但官方不推荐

 

关于EncryptTrustServerCertificate参数,可参考:Use TrustServerCertificate

Encrypt connection string/attributeTrust Server Certificate connection string/attributeResult
No/Optional Ignored No encryption occurs.
Yes/Mandatory No Encryption occurs only if there's a verifiable server certificate, otherwise the connection attempt fails.
Yes/Mandatory Yes Encryption always occurs, but may use a self-signed server certificate.
Strict1 Ignored Encryption always occurs and must use a verifiable server certificate, otherwise the connection attempt fails.

 

小结

结合本次及之前遇到的问题,SQL Server连接报错,有以下几种原因:

  • 客户端/服务端间TLS版本不兼容

  • 服务器证书有问题,客户端校验不通过

最后附一张HTTPS连接的建立过程图:

 

参考资料

MSSQL · 最佳实践 · 使用SSL加密连接

HTTPS介绍及加密的过程

posted @ 2024-05-14 11:01  雪飞鸿  阅读(86)  评论(0编辑  收藏  举报