场景:
项目中有一块功能是检测数据库连接的,测试完到现场报出连接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的关系和影响;这波很亏;