場景:
項目中有一塊功能是檢測數據庫連接的,測試完到現場報出連接postgresql測試失敗的情況;
然鵝,我的代碼里邊通用函數連接都是通過用戶密碼驗證的.這里出現了SSL的報錯;難道是服務端配置強制要求證書驗證?
而且測試環境中是可以正常連接的.那我們就先對比一下現場環境和測試環境的服務端配置好了;
處理過程:
1.對比測試環境和現場環境;
登錄測試環境postgresql所在的服務器用戶, psql
登錄成功, show config_file;
退出psql,查看配置; cat /var/lib/pgsql/data/postgresql.conf | grep ssl
我們可以看到ssl相關配置都注釋掉的;也就是說測試環境的配置是不支持ssl證書驗證的;
那我們看看現場環境; wtf,現場同事說data目錄下沒有配置文件;他們安裝這個postgresql是通過一個drdb的工具安裝的;百度一波只有drbd,線索斷了啊!
2. 查資料嘗試:
網上有文章支持,這個報錯有可能是ssl版本/協議不對導致的; 查 openssl version
ssl版本一模一樣.
病急亂投醫,檢查數據庫版本; select "version"();
postgres版本一模一樣.
僵住了.
查下官方文檔.關於ssl的說明;
ssl證書驗證高安全性的策略的話是需要在服務端和客戶端配置證書,sslmode的級別是在verify-ca和verify-full;
大膽猜測一下,當服務端不設置ssl認證時(測試環境),
客戶端可以不做sslmode配置;當服務端設置了ssl認證時,客戶端連接就需要說明自己的sslmode了.目測為需要配置sslmode=disable,
3.做測試代碼測試;
package com.springboot.demo.testDemo.pgjdbc;
import java.sql.Connection;
import java.sql.DriverManager;
/**
* @Date 2020/6/10 16:44
* @Author zhang.fanlc
* @Description
**/
public class PgJDBC {
public static void main(String[] args) {
String url = "jdbc:postgresql://[ip]:[port]/[dbName]?sslmode=disable";
String driver = "org.postgresql.Driver";
String user = "test";
String pass = "test";
try {
Class.forName(driver);
System.out.println("開始連接...!");
Connection conn = DriverManager.getConnection(url,user,pass);
if(conn != null){
System.out.println("連接成功!");
}
}catch(Exception e){
e.printStackTrace();
}
}
}
把PgJDBC.java拷貝到現場環境;
vi PgJDBC.java, 去掉 package聲明;
設置依賴,vi setEnv.sh ,export CLASSPATH=.:/home/cmspmn/lib/postgresql-42.2.8.jar:,保存,./setEnv.sh,執行;
javac PgJDBC.java
java PgJDBC
爆炸;sslmode=disable不起作用;
爆炸;sslmode=allow;不起作用;
投降投降.放棄掙扎;請教領導,領導說這個sslmode應該和ssl底層的驗證機制匹配的,文檔講的定義不是很准確;讓我用sslmode=requir配置再搞一次;
不得不佩服;
解決方式:
在jdbc連接代碼的url后增加sslmode=requir;
like this
connUrl = "jdbc:postgresql://" + dsIp + ":" + dsPort + "/" + dsName + "?sslmode=require";
問題雖然解決,但是無法探究服務端的配置和客戶端sslmode的關系和影響;這波很虧;