【问题标题】:Exception unable to validate certificate of the target in spring MVC异常无法验证 Spring MVC 中的目标证书
【发布时间】:2015-11-10 03:52:27
【问题描述】:

我正在尝试使用我的用户名和密码从 jira 服务器获取问题详细信息,但我收到一个 ssl 错误,提示无法验证证书

那么如何验证证书

网址:http:local/8080/frr/hello

得到错误:

嵌套异常是 org.springframework.web.client.ResourceAccessException:I/O 错误 获取

的请求

https://jira.example.com/rest/api/2/issue/id”:

sun.security.validator.ValidatorException:PKIX 路径构建失败: sun.security.provider.certpath.SunCertPathBuilderException:无法 找到请求目标的有效认证路径;嵌套异常是 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:PKIX 路径构建失败: sun.security.provider.certpath.SunCertPathBuilderException:无法 找到请求目标的有效认证路径] 根本原因 sun.security.provider.certpath.SunCertPathBuilderException:无法 找到请求目标的有效认证路径

我的 Service.class 代码

@Controller
public class Service{


    @RequestMapping("/hello")


     public String Data(ModelMap model){

        RestTemplate restTemplate = new RestTemplate();

        ResponseEntity<String> result = restTemplate.exchange("https://jira.example.com/rest/api/2/issue/id",  HttpMethod.GET, new HttpEntity<String>(createHeaders("username", "password")), String.class);

        model.addAttribute("message", result);


        return "helloworld";
    }

    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders createHeaders( String username, String password ){
        HttpHeaders header =  new HttpHeaders();
        String auth = username + ":" + password;
        byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII")) );
        String base64Creds = "Basic " + new String( encodedAuth );
        header.add("Authorization", "Basic " + base64Creds);
        return header;
    }   
}

【问题讨论】:

    标签: java spring validation spring-mvc ssl


    【解决方案1】:

    您面临的问题是您的应用程序无法验证您尝试连接的外部服务器,因为其证书不受信任

    简而言之就是:

    • 您的应用程序尝试通过安全 (HTTPS) 通道连接到 Jira 实例
    • 建立安全连接,应用程序下载证书
    • 应用程序通过尝试将证书追溯到已知 CA(保存在 JRE 证书存储中)来检查证书的有效性
    • 证书检查失败,因为证书是自签名的(很可能)或过期等。

    如果此 Jira 实例在本地(由您的公司托管),那么拥有自签名证书的可能性不大。在这种情况下,证书不是由已知 CA 颁发的,因此如果您希望信任它,您需要手动注册它

    首先获取证书:

    openssl s_client -connect jira.example.com:443 < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > public.crt
    

    然后将其导入您自己的密钥库:

    $JAVA_HOME/keytool -import -alias <server_name> -keystore $JAVA_HOME/lib/security/cacerts -file public.crt
    

    注意:以上命令适用于 Unix 环境。在 Windows 下,我建议从命令行使用类似的 openssl,但也有用于相同目的的 GUI 工具。

    【讨论】:

    • 获取证书后如何使用它来验证服务器证书
    • 获得证书文件后,您只需将其导入应用程序正在使用的密钥库中。找到您使用的 Java 安装,然后转到:JAVA_DIR/lib/security/cacerts。
    • 我已包含证书并尝试进行身份验证,但我无法通过身份验证获得 401 状态,请参阅stackoverflow.com/questions/32064672/…
    • 状态 401 是一个不同的问题。得到这意味着您的应用级身份验证失败,但这也意味着 HTTPS 握手成功,因此本文中的问题已解决。
    • 是的,我知道我在问你能不能解决这个问题
    【解决方案2】:

    如果您在导入 @Gergely Bacso 指示的证书后仍然遇到证书问题,请确保您已链接到您的 IDE 或命令行中的 java.exe 或 javaw.exe 二进制文件用于运行您的Java 应用程序是来自 JRE 而不是 JDK 的应用程序,即使在 cacerts 密钥库中安装证书后,我也遇到了证书错误,直到我意识到我使用的二进制文件来自 JDK。在我切换到 JRE 的路径后,一切都按预期进行,我能够成功连接。我希望它可以节省人们尝试调试问题的时间。

    【讨论】:

      【解决方案3】:

      检查文件$JAVA_HOME/lib/security/cacerts是否存在! 在我的例子中,它不是一个文件,而是一个指向 /etc/ssl/certs/java/cacerts 的链接,而且这也是一个指向自身的链接(什么???),因此 JVM 无法找到该文件。

      解决方案: 将真正的 cacerts 文件(我从另一个 JDK 中完成)复制到 /etc/ssl/certs/java/ 目录,它会解决你的问题 :)

      【讨论】:

        【解决方案4】:

        你可以替换

        String base64Creds = "Basic " + new String( encodedAuth );
        

        String base64Creds = new String( encodedAuth ); //"Basic " String duplicated
        

        【讨论】:

          猜你喜欢
          • 2015-11-10
          • 2012-05-11
          • 2017-11-23
          • 2017-03-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-18
          • 2021-03-18
          相关资源
          最近更新 更多