The problem appears when your server has self signed certificate. To workaround it you can add this certificate to the list of trusted certificates of your JVM.
最近开始研究gitlab api的一些调用方式,在用api做一些gitlab操作的时候,遇到一个问题:
使用postman等等工具调用发现是ok的,但是用java去请求对应的接口会报错,如下:
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
... 22 more
|
|
下面是对应的解决脚本:java-cert-importer.sh
#!/usr/bin/env bash
# Exit on error
set -e
# Ensure script is running as root
if [ "$EUID" -ne 0 ]
then echo "WARN: Please run as root (sudo)"
exit 1
fi
# Check required commands
command -v openssl >/dev/null 2>&1 || { echo "Required command 'openssl' not installed. Aborting." >&2; exit 1; }
command -v keytool >/dev/null 2>&1 || { echo "Required command 'keytool' not installed. Aborting." >&2; exit 1; }
# Get command line args
host=$1; port=${2:-443}; deleteCmd=${3:-${2}}
# Check host argument
if [ ! ${host} ]; then
cat << EOF
Please enter required parameter(s)
usage: ./java-cert-importer.sh <host> [ <port> | default=443 ] [ -d | --delete ]
EOF
exit 1
fi;
if [ "$JAVA_HOME" ]; then
javahome=${JAVA_HOME}
elif [[ "$OSTYPE" == "linux-gnu" ]]; then # Linux
javahome=$(readlink -f $(which java) | sed "s:bin/java::")
elif [[ "$OSTYPE" == "darwin"* ]]; then # Mac OS X
javahome="$(/usr/libexec/java_home)/jre"
fi
if [ ! "$javahome" ]; then
echo "WARN: Java home cannot be found."
exit 1
elif [ ! -d "$javahome" ]; then
echo "WARN: Detected Java home does not exists: $javahome"
exit 1
fi
echo "Detected Java Home: $javahome"
# Set cacerts file path
cacertspath=${javahome}/lib/security/cacerts
cacertsbackup="${cacertspath}.$$.backup"
if ( [ "$deleteCmd" == "-d" ] || [ "$deleteCmd" == "--delete" ] ); then
sudo keytool -delete -alias ${host} -keystore ${cacertspath} -storepass changeit
echo "Certificate is deleted for ${host}"
exit 0
fi
# Get host info from user
#read -p "Enter server host (E.g. example.com) : " host
#read -p "Enter server port (Default 443) : " port
# create temp file
tmpfile="/tmp/${host}.$$.crt"
# Create java cacerts backup file
cp ${cacertspath} ${cacertsbackup}
echo "Java CaCerts Backup: ${cacertsbackup}"
# Get certificate from speficied host
openssl x509 -in <(openssl s_client -connect ${host}:${port} -prexit 2>/dev/null) -out ${tmpfile}
# Import certificate into java cacerts file
sudo keytool -importcert -file ${tmpfile} -alias ${host} -keystore ${cacertspath} -storepass changeit
# Remove temp certificate file
rm ${tmpfile}
# Check certificate alias name (same with host) that imported successfully
result=$(keytool -list -v -keystore ${cacertspath} -storepass changeit | grep "Alias name: ${host}")
# Show results to user
if [ "$result" ]; then
echo "Success: Certificate is imported to java cacerts for ${host}";
else
echo "Error: Something went wrong";
fi;
执行脚本:
chmod u+x
java-cert-importer.sh
安装证书:
sudo ./java-cert-importer.sh gitlab.yourcompanyhost.com
删除证书:
sudo ./java-cert-importer.sh
gitlab.yourcompanyhost.com
--delete
注意:
1. 上述脚本修改的只是jdk/lib下的security,还需要修改jre/lib/security下的,需要手动修改下脚本,这里就不做修改了。
2. 记得要先要配置java的环境变量。
提醒:拷贝脚本内容有问题的话,可以直接下载附件。