某次项目需要升级,在中午给了10分钟升级,一顿操作后启动失败,报错日志捞出如下:
2025-01-13 11:37:08.751 [Druid-ConnectionPool-Create-1929713950] [traceId = ] ERROR com.alibaba.druid.pool.DruidDataSource - create connection SQLException, url: jdbc:p6spy:sqlserver://192.168.*.*1:1433;databaseName=***, errorCode 0, state 08S01
com.microsoft.sqlserver.jdbc.SQLServerException: 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target”。 ClientConnectionId:fa45e14e-f84d-44c7-be68-0a4d776a8a56
at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:3680)
at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:2047)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:3204)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:2833)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:2671)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:1640)
at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:936)
at com.p6spy.engine.spy.P6SpyDriver.connect(P6SpyDriver.java:102)
at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1644)
at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1710)
at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2779)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find vali
d certification path to requested target
at sun.security.ssl.Alert.createSSLException(Alert.java:131)
at sun.security.ssl.TransportContext.fatal(TransportContext.java:370)
at sun.security.ssl.TransportContext.fatal(TransportContext.java:313)
at sun.security.ssl.TransportContext.fatal(TransportContext.java:308)
at sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:652)
at sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:471)
at sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:367)
at sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:376)
at sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:479)
at sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:457)
at sun.security.ssl.TransportContext.dispatch(TransportContext.java:200)
at sun.security.ssl.SSLTransport.decode(SSLTransport.java:155)
at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1320)
at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1233)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:417)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:389)
at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1955)
... 9 common frames omitted
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested tar
get
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
at sun.security.validator.Validator.validate(Validator.java:271)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:312)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:232)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:109)
at com.microsoft.sqlserver.jdbc.TDSChannel$HostNameOverrideX509TrustManager.checkServerTrusted(IOBuffer.java:1636)
at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:1257)
at sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:636)
... 21 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
... 29 common frames omitted
关键报错: 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接
驱动包:
mssql-jdbc-10.2.3.jre8.jar
spring-jdbc-5.3.39.jar
druid-1.1.22.jar
druid-spring-boot-starter-1.1.22.jar
dynamic-datasource-spring-boot-starter-3.4.1.jar
解决方法(以下回答来自于通义):
对于SQL Server数据库,通过JDBC连接时遇到SSL/TLS相关的错误,可以采取以下步骤来解决:
-
禁用加密(不推荐用于生产环境): 如果您在开发或测试环境中,并且不需要SSL/TLS加密,可以在JDBC URL中添加
encrypt=false参数来关闭加密。String url = "jdbc:sqlserver://hostname:port;databaseName=mydb;encrypt=false"; -
启用加密并信任服务器证书: 如果需要使用SSL/TLS加密,但不想验证服务器证书(例如,在受控的内部网络中),可以在JDBC URL中设置
encrypt=true和trustServerCertificate=true。这会绕过证书验证,但是请注意,这样做可能会使连接易受中间人攻击的影响。String url = "jdbc:sqlserver://hostname:port;databaseName=mydb;encrypt=true;trustServerCertificate=true"; -
提供有效的SSL证书: 如果您希望完全验证服务器证书,确保客户端有服务器的SSL证书,并且配置正确。您可以将证书导入到Java的信任库(truststore)中。这通常涉及到使用
keytool命令行工具。-
导入证书到信任库:
keytool -import -alias sqlserver -file server-cert.cer -keystore client-truststore.jks -
在启动Java应用程序时指定信任库:
java -Djavax.net.ssl.trustStore=client-truststore.jks -Djavax.net.ssl.trustStorePassword=mypassword MyApplication
-
-
检查SQL Server配置: 确保SQL Server已经配置为接受加密连接。这可以通过SQL Server Configuration Manager完成。具体步骤如下:
- 打开SQL Server Configuration Manager。
- 导航到“SQL Server Network Configuration” -> “Protocols for MSSQLSERVER”。
- 右键点击“TCP/IP”,选择“属性”。
- 转到“Flags”选项卡,找到“Force Encryption”选项,将其设置为“Yes”或“No”取决于您的需求。
- 如果启用了强制加密,还需要配置“Certificates”选项卡,选择一个有效的SSL证书。
-
更新JDBC驱动: 确保您使用的JDBC驱动版本是最新的,并且支持与SQL Server的SSL连接。有时更新到最新的驱动版本可以解决问题。您可以从Microsoft官方网站下载最新的SQL Server JDBC驱动。
-
查看日志和错误信息: 仔细阅读错误消息和日志文件,它们通常会给出更具体的信息,指出问题所在。根据这些信息,您可以更有针对性地进行排查。
-
联系数据库管理员: 如果以上步骤都不能解决问题,或者您不确定如何配置SSL,最好联系数据库管理员获取帮助。他们可以提供有关服务器配置的具体信息,并协助解决问题。
-
防火墙和网络配置: 检查是否有防火墙规则阻止了SSL端口的流量。默认情况下,SQL Server使用1433端口,但如果启用了SSL,则可能需要确保防火墙允许该端口上的TLS流量。
因为是纯内网环境,最终使用方法一,项目已上线情况下,优先解决项目无法启动问题
启动成功,结束(小项目,勿喷)