You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java可执行Jar运行出现PKIX证书路径验证失败问题求助

PKIX路径构建失败问题排查与解决

问题描述

我用Java 8开发了一个需通过Jar包执行的应用,启动类为DescargaMensajesEntidadesInit,代码如下:

public class DescargaMensajesEntidadesInit {
    private static Logger log = LoggerFactory.getLogger(DescargaMensajesEntidadesInit.class);
    public static void main(String[] args) {
        // TODO Apéndice de método generado automáticamente
        //Verificamos que se pasen tres argumentos
        if (args.length < 4) {
            log.warn("Uso: java Main <idAplicacion> <ruta_certificado> <clave_certificado> <entidad>");
            return;
        }
        //Primer argumento: La identificación de la aplicación
        String idAplicacion = args[0];
        //Segundo argumento: ruta al archivo de certificado
        String rutaCertificado = args[1];
        File certificado = new File(rutaCertificado);
        //Tercer argumento: clave del certificado
        String claveCertificado = args[2];
        //Cuarto argumento: entidad (debe cumplir con la expresión regular [0-9]{8})
        String entidad = args[3];
        String patronEntidad = "[0-9]{10}";
        //Validamos que el argumento "entidad" cumple con la expresión regular
        if (!entidad.matches(patronEntidad)) {
            log.warn("Error: La entidad debe ser un string de 10 dígitos (ejemplo: 1234567890).");
            return;
        }
        //Verificamos si el archivo de certificado existe y es un archivo
        if (certificado.exists() && certificado.isFile()) {
            log.info("Identificacion de la aplicacion: " + idAplicacion);
            log.info("Ruta del certificado: " + rutaCertificado);
            log.info("Clave del certificado: " + claveCertificado);
            log.info("Entidad: " + entidad);
            //Llamamos al Servicio descarga de mensajes
            DescargaMensajesEntrada entrada = new DescargaMensajesEntrada();
            entrada.setIdAplicacion(idAplicacion);
            entrada.setFicheroP12(rutaCertificado);
            entrada.setPasswordP12(claveCertificado.toCharArray());
            entrada.setIdEntidad(entidad);
            String respuesta = descargaMensajesEntidades(entrada);
            log.info(respuesta);
        } else {
            log.warn("El archivo de certificado no existe o no es un archivo válido.");
        }
    }
    private static String descargaMensajesEntidades(DescargaMensajesEntrada entrada)  {
        String respuesta = "";
        try {
            DescargaMensajesEntidadesReturn response = new DescargaMensajesEntidadesReturn();
            DescargarMensajesEntidadesService descargarMensajesEntidadesService = new DescargarMensajesEntidadesServiceImpl();
            response = descargarMensajesEntidadesService.ejecutar(entrada);
            respuesta = response.getRespuestaCorrecta().getOut();
            if("".equals(respuesta) || respuesta == null) {
                respuesta = response.getError().getTexto();
            }
        } catch (DescargaMensajesEntidadesFault_Exception e) {
            log.error("Problemas en el servicio de Descarga de mensajes, motivo: " + e.getMessage());
        }
        return respuesta;
    }
}

直接运行并传入参数时程序正常工作,但打包为可执行Jar后,执行以下命令出现PKIX路径构建失败的SSL握手错误:

java -Djavax.net.ssl.trustStore=CERTLEXNET.p12 -Djavax.net.ssl.trustStorePassword=8ba73c7240 -jar palex.jar "PALEXWS" "/certificado/CERTLEXNET.p12" "8ba73c7240" "2807906202"

编译Jar使用jdk1.8.0_231,运行环境为jre1.8.0_431,不确定是否与版本差异有关,求解决。

解决步骤

1. 指定信任库类型参数

P12格式证书需明确指定信任库类型,JVM默认使用JKS格式,修改执行命令添加-Djavax.net.ssl.trustStoreType=PKCS12:

java -Djavax.net.ssl.trustStore=CERTLEXNET.p12 -Djavax.net.ssl.trustStorePassword=8ba73c7240 -Djavax.net.ssl.trustStoreType=PKCS12 -jar palex.jar "PALEXWS" "/certificado/CERTLEXNET.p12" "8ba73c7240" "2807906202"

2. 校验证书路径与权限

  • 命令中-Djavax.net.ssl.trustStore=CERTLEXNET.p12用的是相对路径,确认执行命令的工作目录下存在该文件,或改用绝对路径(如-Djavax.net.ssl.trustStore=/certificado/CERTLEXNET.p12)
  • 确保运行程序的用户对证书文件有读取权限

3. 验证证书完整性

用keytool工具检查证书是否有效:

keytool -list -keystore CERTLEXNET.p12 -storetype PKCS12 -storepass 8ba73c7240

若命令报错,说明证书损坏或密码错误,需重新获取正确证书。

4. 处理JDK/JRE版本差异

jdk1.8.0_231到jre1.8.0_431的更新可能调整了SSL信任策略,可尝试:

  • 切换编译环境为jre1.8.0_431,重新打包Jar
  • 将证书导入JRE默认信任库cacerts:
keytool -importkeystore -srckeystore CERTLEXNET.p12 -srcstoretype PKCS12 -srcstorepass 8ba73c7240 -destkeystore $JAVA_HOME/jre/lib/security/cacerts -deststoretype JKS -deststorepass changeit

(注:changeit是cacerts默认密码,若已修改请替换)

5. 程序内自定义SSL上下文

若上述方法无效,可在代码中手动加载证书,不依赖JVM参数:

// 在调用descargaMensajesEntidades方法前添加以下代码
try {
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    FileInputStream fis = new FileInputStream(rutaCertificado);
    keyStore.load(fis, claveCertificado.toCharArray());
    
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(keyStore);
    
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
    SSLContext.setDefault(sslContext);
} catch (Exception e) {
    log.error("Error al configurar SSL context: " + e.getMessage());
}

内容的提问来源于stack exchange,提问作者Jesus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 09:49:56