本文中含有需要您注意的重要提示信息,忽略該信息可能對您的業務造成影響,請務必仔細閱讀。
本文介紹配置了SSL鏈路加密后,如何通過pgAdmin、psql命令行終端以及JDBC連接數據庫。
前提條件
已開啟SSL鏈路加密。如果未開啟,請參見使用云端證書快速開啟SSL加密或使用自定義證書開啟SSL加密。
已獲取如下文件。
操作步驟
pgAdmin客戶端SSL連接
pgAdmin客戶端是PostgreSQL官方推薦的數據庫連接工具,在PostgreSQL官方網站下載并安裝PostgreSQL時,將會自動安裝pgAdmin 4客戶端。下文以pgAdmin 4 V6.2.0
為例,介紹如何連接RDS PostgreSQL實例。
如果您不想安裝PostgreSQL,也可以單獨下載pgAdmin客戶端,僅用于連接遠程數據庫。
啟動pgAdmin 4客戶端。
說明高版本客戶端首次登錄需要設置Master Password用于保護保存的密碼和其他憑據。
右鍵單擊Servers,選擇
。在General頁簽設置連接名稱。
選擇Connection標簽頁,輸入要連接的實例信息。
參數
說明
Host name/address
RDS PostgreSQL實例的連接地址及對應的端口。
若通過內網連接,需輸入RDS實例的內網地址和內網端口。
若使用外網連接,需輸入RDS實例的外網地址和外網端口。
您可以在RDS PostgreSQL實例的數據庫連接頁面查看。
更多信息,請參見查看或修改連接地址和端口。
Port
Username
RDS PostgreSQL實例的賬號和密碼。
創建RDS實例的賬號請參見創建賬號和數據庫。
Password
選擇Parameters標簽頁,添加SSL認證方式相關參數并配置證書。
參數
說明
SSL mode
PostgreSQL數據庫開啟SSL鏈路加密后,表示允許客戶端通過SSL連接數據庫,在客戶端連接數據庫時,請根據以下場景選擇SSL mode參數的取值。
Require、Verify-CA和Verify-Full含義如下:
Require:只對數據鏈路加密,并不驗證數據庫的真實性。
Verify-CA:加密數據鏈路,同時驗證數據庫的真實性。
Verify-Full:加密數據鏈路,驗證數據庫的真實性,同時比對證書內的CN或DNS與連接時配置的數據庫連接地址是否一致。
Client certificate
如果完成了配置客戶端CA證書,則需要配置此參數,表示客戶端證書(client.crt)。
Client certificate key
如果完成了配置客戶端CA證書,則需要配置此參數,表示客戶端證書私鑰(client.key)。
Root certificate
當SSL mode取值為Verify-CA或Verify-Full時,需要配置此參數,表示數據庫CA證書路徑。
說明本示例中,客戶端證書(client.crt)、客戶端證書私鑰(client.key)和數據庫CA證書(server-ca.crt)的文件路徑請根據實際情況配置。
本示例以配置自定義證書為例,除自定義證書外,您也可以配置云端證書,例如將
server-ca.crt
替換為ApsaraDB-CA-Chain.pem
。
單擊Save。
若連接信息無誤,會出現如下界面,則表示連接成功。
重要postgres是RDS實例默認的系統數據庫,請勿在該數據庫中進行任何操作。
psql命令行終端SSL連接
本步驟依賴本地PostgreSQL客戶端自帶的psql命令行工具,請確保您已安裝PostgreSQL客戶端,具體請參見PostgreSQL官方文檔。
在/var/lib/pgsql目錄下創建.postgresql文件夾。
mkdir /var/lib/pgsql/.postgresql
將如下文件拷貝到.postgresql文件夾中。
(可選)客戶端證書(client.crt)、客戶端證書私鑰(client.key):如果在RDS控制臺配置了客戶端CA證書,則需要配置,獲取方法請參見配置客戶端CA證書。
cp client.crt client.key server-ca.crt /var/lib/pgsql/.postgresql/
說明本示例中,客戶端證書(client.crt)、客戶端證書私鑰(client.key)和數據庫CA證書(server-ca.crt)的文件路徑請根據實際情況配置。
本示例以配置自定義證書為例,除自定義證書外,您也可以配置云端證書,例如將
server-ca.crt
替換為ApsaraDB-CA-Chain.pem
。
修改.postgresql文件夾權限。
chown postgres:postgres /var/lib/pgsql/.postgresql/* chmod 600 /var/lib/pgsql/.postgresql/*
使用如下命令編輯postgres用戶的環境變量。
vim /var/lib/pgsql/.bash_profile
輸入
i
進入編輯模式,補充如下內容。export PGSSLCERT="/var/lib/pgsql/.postgresql/client.crt" export PGSSLKEY="/var/lib/pgsql/.postgresql/client.key" export PGSSLROOTCERT="/var/lib/pgsql/.postgresql/ca1.crt"
使用
Esc
退出編輯模式,然后輸入:wq
保存并退出。重新加載環境變量。
source .bash_profile
設置連接時客戶端對數據庫的認證方式。
export PGSSLMODE="verify-full"
PostgreSQL數據庫開啟SSL鏈路加密后,表示允許客戶端通過SSL連接數據庫,在客戶端連接數據庫時,請根據以下場景選擇PGSSLMODE參數的取值。
數據庫是否配置客戶端訪問控制
是否需要通過SSL連接
PGSSLMODE取值
否
是
require、verify-ca或verify-full
否
disable
是
必須使用SSL
require、verify-ca或verify-full
說明require、verify-ca和verify-full含義如下:
require:只對數據鏈路加密,并不驗證數據庫的真實性。
verify-ca:加密數據鏈路,同時驗證數據庫的真實性。
verify-full:加密數據鏈路,驗證數據庫的真實性,同時比對證書內的CN或DNS與連接時配置的數據庫連接地址是否一致。
連接數據庫。
psql -h <數據庫連接地址> -U <用戶名> -p <端口號> -d <數據庫名>
各參數在RDS控制臺的獲取位置:
參數
獲取方式
數據庫連接地址
加密的連接地址,通過SSL頁面中保護主機參數獲取。
用戶名
通過賬號管理頁面獲取用戶名。
端口號
默認5432,如果您修改過,通過數據庫連接頁面獲取。
數據庫名
postgres是RDS實例默認的系統數據庫,請勿在該數據庫中進行任何操作。如果您需要連接RDS實例下創建的其他數據庫,可從數據庫管理頁面獲取。
JDBC SSL連接
下載如下文件到本地。
將客戶端私鑰(client.key)轉換為pk8格式。
openssl pkcs8 -topk8 -inform PEM -in client.key -outform der -out client.pk8 -v1 PBE-MD5-DES # 需要輸入密碼,連接時需要使用 Enter Encryption Password: Verifying - Enter Encryption Password:
警告該命令必須在應用程序所在設備上執行,使用應用程序所在設備上的openssl命令將私鑰轉換為pk8格式,否則可能提示如下報錯:
org.postgresql.util.PSQLException: Could not decrypt SSL key file C:/Users/XXX/XXX/client.pk8
org.postgresql.util.PSQLException: SSL error: Received fatal alert: unexpected_message
以Maven項目為例,在pom.xml中導入PostgreSQL的Maven依賴。
<dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.2.10</version> </dependency>
在業務代碼中編寫JDBC SSL連接PostgreSQL。
說明本示例以配置自定義證書為例,除自定義證書外,您也可以配置云端證書,例如將
server-ca.crt
替換為ApsaraDB-CA-Chain.pem
。public class PgSslDemo { public static void main(String[] args) { // 設置RDS PostgreSQL實例的連接地址 String hostname = "pgm-bp1gclw58u36s6****.pg.rds.aliyuncs.com"; // 設置RDS PostgreSQL實例的連接端口 String port = "5432"; // 設置待連接的數據庫名 String dbname = "postgres"; String jdbcUrl = "jdbc:postgresql://" + hostname + ":" + port + "/" + dbname + "?binaryTransfer=true"; Properties properties = new Properties(); // 設置連接數據庫的用戶名 properties.setProperty("user", "test_user"); //設置連接數據庫的密碼 properties.setProperty("password", "test_pwd"); // 設置證書存放路徑 String path = "D:\\ssl\\"; // 配置以SSL訪問 properties.setProperty("ssl", "true"); //設置證書授權機構的公鑰名 properties.setProperty("sslrootcert", path + "/" + "server-ca.crt"); //設置客戶端證書私鑰名 properties.setProperty("sslkey", path + "/" + "client.pk8"); //設置客戶端證書名 properties.setProperty("sslcert", path + "/" + "client.crt"); //填寫將私鑰key格式轉換為pk8格式時設置的密碼 properties.setProperty("sslpassword", "test_ssl_pwd"); // 配置SSL模式,可選值為require、verify-ca、verify-full properties.setProperty("sslmode", "verify-ca"); try { Class.forName("org.postgresql.Driver"); Connection connection = DriverManager.getConnection(jdbcUrl, properties); //本示例中,假設在postgres數據庫中存在表example,此處以查詢表example數據為例。 PreparedStatement preparedStatement = connection.prepareStatement("select * from " + "students01"); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { ResultSetMetaData rsmd = resultSet.getMetaData(); int columnCount = rsmd.getColumnCount(); Map map = new HashMap(); for (int i = 0; i < columnCount; i++) { map.put(rsmd.getColumnName(i + 1).toLowerCase(), resultSet.getObject(i + 1)); } System.out.println(map); } } catch (Exception exception) { exception.printStackTrace(); } } }