SSL链接一个很奇怪的错误

[TOC]

  • 背景

    在git代码相同,数据库相同的情况下,测试版本报异常,但是本地的开发版没有异常出现,同事电脑上的代码和数据库都一致,也报异常。一直搞不懂原因。联想到最近换了SSL证书,排除证书过期,域名不一直以后,google之,得到答案,参考[这里](https://stackoverflow.com/questions/26180650/unable-to-find-valid-certification-path-to-requested-target-but-browser-says),发现证书链在根证书中没有被信任。
    
  • 异常报告

    Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    
    Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    
    Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    
  • 异常原因

    • 原因一:你的SSL证书和域名不匹配

      就是颁发的证书域名和你真正访问的域名不一致
      
    • 原因二:证书链不完整

      证书链由两个环节组成—信任锚(CA 证书)环节和已签名证书环节。自我签名的证书仅有一个环节的长度—信任锚环节就是已签名证书本身。
      
      证书链可以有任意环节的长度,所以在三节的链中,信任锚证书CA 环节可以对中间证书签名;中间证书的所有者可以用自己的私钥对另一个证书签名。CertPath API 可以用来遍历证书链以验证有效性,也可以用来构造这些信任链。
      
      证书最初生成时是一个自签名证书。自签名证书是其签发者(签名者)与主题(其公共密钥由该证书进行验证的实体)相同的证书。如果拥有者向 CA 发送证书签名请求 (CSR),然后输入响应,自签名证书将被证书链替换。链的底部是由 CA 发布的、用于验证主题的公共密钥的证书(回复)。链中的下一个证书是验证 CA 的公共密钥的证书。通常,这是一个自签名证书(即,来自 CA、用于验证其自身的公共密钥的证书)并且是链中的最后一个证书。
      
      在其他情况下,CA 可能会返回一个证书链。在此情况下,链的底部证书是相同的(由 CA 签发的证书,用于验证密钥条目的公共密钥),但是链中的第二个证书是由其他 CA 签发的证书,用于验证您向其发送了 CSR 的 CA 的公共密钥。然后,链中的下一个证书是用于验证第二个 CA 的密钥的证书,依此类推,直至到达自签名的[根证书]。因此,链中的每个证书(第一个证书之后的证书)都需要验证链中前一个证书的签名者的[公共密钥]。

      微信截图_20180113110420.png

    • 根证书没有被信任

      证书链是由根证书-----CA-----已签名证书这条证书链依次被信任,如果根证书不被信任,那么由该根证书签发的所有颁发者证书都不被信任,进而导致颁发者颁发的所有证书都不被信任
      
      ​
      
  • 解决办法

    • 换个证书,换个JRE中默认被信任根证书签发的CA证书颁发的证书(这里提供jre中默认信任的证书列表)

      算了,给出查找方法吧,在配置好java运行环境的情况下,
      windows运行
      keytool -list -keystore %JAVA_HOME%/jre/lib/security/cacerts
      Linux运行
      keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts
      
      输入密钥库口令: 
      
      *****************  WARNING WARNING WARNING  *****************
      * 存储在您的密钥库中的信息的完整性  *
      * 尚未经过验证!  为了验证其完整性, *
      * 必须提供密钥库口令。                  *
      *****************  WARNING WARNING WARNING  *****************
      
      密钥库类型: JKS
      密钥库提供方: SUN
      
      您的密钥库包含 104 个条目
      ....
      然后这里会列出你所有的被信任的根证书颁发者
      
    • 手动将你的证书,CA证书和根证书引入到jre的信任列表中

      windows:
      keytool -import -alias my-cert -file c:\cert.crt -keystore %JAVA_HOME%/jre/lib/security/cacerts
      
      linux:
      
      keytool -import -alias my-cert -file /your/cert/path/cert.crt -keystore $JAVA_HOME/jre/lib/security/cacerts
      
上一篇
下一篇