知識庫 / Spring / Spring Boot RSS 訂閱

MySQL 和 Spring Boot 應用 TLS 設置

Security,Spring Boot
HongKong
4
11:52 AM · Dec 06 ,2025

1. 概述

未加密的 MySQL 服務器與客户端之間的連接可能暴露網絡傳輸中的數據。對於生產環境的應用,我們應該將所有通信轉移到通過 TLS(傳輸層安全)協議的加密連接中。

在本教程中,我們將學習如何在一個 MySQL 服務器上啓用安全連接。此外,我們還將配置 Spring Boot 應用程序以使用此安全連接。

2. 使用 TLS 的原因

首先,讓我們瞭解一些 TLS 的基本概念。

TLS 協議使用加密算法,以確保通過網絡傳輸的數據可以得到信任,並且不會被篡改或監視。它具有檢測數據更改、丟失或重放攻擊的機制。 TLS 還包含使用 X.509 標準提供的身份驗證算法。

加密連接會增加一層安全保障,使網絡流量中的數據無法被讀取。

配置 MySQL 服務器和客户端之間的安全連接,可以實現更好的身份驗證、數據完整性和可信度。 此外,MySQL 服務器還可以對客户端的身份進行額外的檢查。

然而,這種安全連接會帶來性能懲罰,因為加密會消耗計算資源。 性能成本的嚴重程度取決於多種因素,例如查詢大小、數據負載、服務器硬件、網絡帶寬和其他因素。

3. 配置 MySQL 服務器上的 TLS 連接

MySQL 服務器以連接為基礎進行加密,並且可以針對特定用户強制或可選地啓用此功能。MySQL 支持通過安裝的 OpenSSL 庫在運行時執行與 SSL 加密相關的操作。

我們可以使用 JDBC 驅動程序 Connector/J 在初始握手之後,對客户端和服務器之間的數據進行加密。

MySQL 8.0.28 或更高版本僅支持 TLS v1.2 和 TLS v1.3。它不再支持較早版本的 TLS (v1 和 v1.1)。

服務器身份驗證可以啓用,使用通過受信任的根證書頒發機構簽發的證書或自簽名證書。

此外,通常的做法是在生產環境中構建自己的根 CA 文件。

服務器還可以驗證客户端的 SSL 證書並對客户端身份執行額外的檢查。

3.1. 使用 TLS 證書配置 MySQL 服務器

我們將使用 <em require_secure_transport</em> 屬性和默認生成的證書,在 MySQL 服務器上啓用安全傳輸。

以下是如何通過 <em docker-compose.yml</em> 文件快速啓動 MySQL 服務器的示例:

version: '3.8'

services:
  mysql-service:
    image: "mysql/mysql-server:8.0.30"
    container_name: mysql-db
    command: [ "mysqld",
      "--require_secure_transport=ON",
      "--default_authentication_plugin=mysql_native_password",
      "--general_log=ON" ]
    ports:
      - "3306:3306"
    volumes:
      - type: bind
        source: ./data
        target: /var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_HOST: "%"
      MYSQL_ROOT_PASSWORD: "Password2022"
      MYSQL_DATABASE: test_db

我們應注意,上述MySQL Server 使用默認證書,位於路徑 /var/lib/mysql

或者,我們可以通過在 docker-compose.yml 中包含一些 mysqld 配置來覆蓋默認證書。

command: [ "mysqld",
  "--require_secure_transport=ON",
  "--ssl-ca=/etc/certs/ca.pem",
  "--ssl-cert=/etc/certs/server-cert.pem",
  "--ssl-key=/etc/certs/server-key.pem",
  ....]

現在,讓我們使用 mysql-service 命令,並使用 docker-compose 命令:

$ docker-compose -p mysql-server up

3.2. 創建用户,使用 X509

可選地,我們可以使用 X509 標準配置 MySQL 服務器,並啓用客户端身份識別。 使用 X509,需要提供有效的客户端證書。 這允許啓用雙向互信 TLS(mTLS)。

下面創建一個使用 X509 並授予對 test_db 數據庫的權限的用户:

mysql> CREATE USER 'test_user'@'%' IDENTIFIED BY 'Password2022' require X509;
mysql> GRANT ALL PRIVILEGES ON test_db.* TO 'test_user'@'%';

我們可以在不進行任何用户證書識別的情況下建立 TLS 連接:

mysql> CREATE USER 'test_user'@'%' IDENTIFIED BY 'Password2022' require SSL;

需要注意的是,如果使用SSL,客户端必須提供信任庫。

4. 配置 Spring Boot 應用程序的 TLS

Spring Boot 應用程序可以通過設置 JDBC URL 並指定一些屬性來配置 JDBC 連接上的 TLS。

有多種方法可以配置 Spring Boot 應用程序使用 TLS 與 MySQL 連接。

在此之前,我們需要將 truststore 和客户端證書轉換為 JKS 格式。

4.1. 將 PEM 文件轉換為 JKS 格式

讓我們將 MySQL 服務器生成的 ca.pemclient-cert.pem 文件轉換為 JKS 格式:

keytool -importcert -alias MySQLCACert.jks -file ./data/ca.pem \
    -keystore ./certs/truststore.jks -storepass mypassword
openssl pkcs12 -export -in ./data/client-cert.pem -inkey ./data/client-key.pem \
    -out ./certs/certificate.p12 -name "certificate"
keytool -importkeystore -srckeystore ./certs/certificate.p12 -srcstoretype pkcs12 -destkeystore ./certs/client-cert.jks

需要注意的是,自Java 9版本起,默認密鑰庫格式為PKCS12

4.2. 使用 application.yml進行配置

TLS 可以通過將 sslMode 設置為 PREFERRED, REQUIRED, VERIFY_CAVERIFY_IDENTITY 來啓用。

PREFERRED 模式會在服務器支持的情況下使用安全連接,否則會回退到未加密連接。

使用 REQUIRED 模式 時,客户端只能使用加密連接。 類似於 REQUIREDVERIFY_CA 模式,VERIFY_CA 模式使用安全連接,並且還通過驗證服務器證書與配置的證書頒發機構 (CA) 證書來驗證。

VERIFY_IDENTITY 模式還會在證書驗證之外,對主機名進行額外的檢查。

還需要向 JDBC URL 添加一些 Connector/J 屬性,例如 trustCertufucateKeyStoreUrl, trustCertificateKeyStorePassword, clientCertificateKeyStoreUrlclientCertificateKeyStorePassword

讓我們在 application.yml 中配置 JDBC URL,並將 sslMode 設置為 VERIFY_CA

spring:
  profiles: "dev2"
  datasource:
    url: >-
         jdbc:mysql://localhost:3306/test_db?
         sslMode=VERIFY_CA&
         trustCertificateKeyStoreUrl=file:/<project-path>/mysql-server/certs/truststore.jks&
         trustCertificateKeyStorePassword=mypassword&
         clientCertificateKeyStoreUrl=file:/<project-path>/mysql-server/certs/client-cert.jks&
         clientCertificateKeyStorePassword=mypassword
    username: test_user
    password: Password2022

請注意,已棄用的屬性 實際上是 的組合。

如果未提供信任證書文件,將會出現相應的錯誤。

Caused by: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
	at java.base/sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:157) ~[na:na]
	at java.base/sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:83) ~[na:na]
	at java.base/java.security.cert.CertPathValidator.validate(CertPathValidator.java:309) ~[na:na]
	at com.mysql.cj.protocol.ExportControlled$X509TrustManagerWrapper.checkServerTrusted(ExportControlled.java:402) ~[mysql-connector-java-8.0.29.jar:8.0.29]

如果缺少客户端證書,將會收到不同的錯誤:

Caused by: java.sql.SQLException: Access denied for user 'test_user'@'172.20.0.1'

4.3. 使用環境變量配置 TLS

或者,我們可以將上述配置設置為環境變量,並將與 SSL 相關的配置作為 JVM 參數包含進來。

讓我們將 TLS 和 Spring 相關的配置添加到環境變量中:

export TRUSTSTORE=./mysql-server/certs/truststore.jks
export TRUSTSTORE_PASSWORD=mypassword
export KEYSTORE=./mysql-server/certs/client-cert.jks
export KEYSTORE_PASSWORD=mypassword
export SPRING_DATASOURCE_URL=jdbc:mysql://localhost:3306/test_db?sslMode=VERIFY_CA
export SPRING_DATASOURCE_USERNAME=test_user
export SPRING_DATASOURCE_PASSWORD=Password2022

然後,讓我們使用上述 SSL 配置運行該應用程序:

$java -Djavax.net.ssl.keyStore=$KEYSTORE \
 -Djavax.net.ssl.keyStorePassword=$KEYSTORE_PASSWORD \
 -Djavax.net.ssl.trustStore=$TRUSTSTORE \
 -Djavax.net.ssl.trustStorePassword=$TRUSTSTORE_PASSWORD \
 -jar ./target/spring-boot-mysql-0.1.0.jar

5. 驗證 TLS 連接

現在,讓我們使用上述任何一種方法運行應用程序,並驗證 TLS 連接。

可以使用 MySQL 服務器的通用日誌或查詢 <span lang="en">process</span><span lang="en">sys</span> admin 表來驗證 TLS 連接。

讓我們使用日誌文件在默認路徑下進行驗證:/var/lib/mysql/

$ cat /var/lib/mysql/7f44397082d7.log
2022-09-17T13:58:25.887830Z        19 Connect   [email protected] on test_db using SSL/TLS

當然,以下是翻譯後的內容:

或者,我們來驗證 test_user 使用的連接:

mysql> SELECT process.thd_id,user,db,ssl_version,ssl_cipher FROM sys.processlist process, sys.session_ssl_status session 
where process.user='[email protected]'and process.thd_id=session.thread_id;+--------+----------------------+---------+-------------+------------------------+
| thd_id | user                 | db      | ssl_version | ssl_cipher             |
+--------+----------------------+---------+-------------+------------------------+
|    167 | [email protected] | test_db | TLSv1.3     | TLS_AES_256_GCM_SHA384 |
|    168 | [email protected] | test_db | TLSv1.3     | TLS_AES_256_GCM_SHA384 |
|    169 | [email protected] | test_db | TLSv1.3     | TLS_AES_256_GCM_SHA384 |

6. 結論

在本文中,我們學習了 TLS 連接到 MySQL 如何確保網絡上傳輸的數據安全。 此外,我們還了解了如何在 Spring Boot 應用程序中配置 TLS 連接到 MySQL 服務器。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.