Java 异常无法在spring MVC中验证目标证书

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32051596/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 11:59:25  来源:igfitidea点击:

Exception unable to validate certificate of the target in spring MVC

javaspringvalidationspring-mvcssl

提问by Labeo

i am trying to get issue details from jira server using my username and password but i am getting an ssl error saying unable to validate certificate

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

so how to validate certificate

那么如何验证证书

url: http:local/8080/frr/hello

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

Getting error:

获取错误:

nested exception is org.springframework.web.client.ResourceAccessException: I/O error on GET request for

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

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is 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] with root cause sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

嵌套异常是 org.springframework.web.client.ResourceAccessException: I/O error on GET request for

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:无法找到请求目标的有效认证路径

my Service.class code

我的 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;
    }   
}

采纳答案by Gergely Bacso

The problem you are facing is that your application cannot validate the external server you are trying to connect to as its certificate is not trusted.

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

What happening in short is:

简而言之,发生的事情是:

  • your application tries to connect to the a Jira instance over a secure (HTTPS) channel
  • to establish the secure connection the application downloads the certificate
  • the application checks the validity of the certificate by trying to trace it back to a known CA (kept in the JRE cert-store)
  • certificate check fails because the cert is self-signed (most likely) or expired, etc.
  • 您的应用程序尝试通过安全 (HTTPS) 通道连接到 Jira 实例
  • 建立安全连接应用程序下载证书
  • 应用程序通过尝试将证书追溯到已知 CA(保存在 JRE 证书存储中)来检查证书的有效性
  • 证书检查失败,因为证书是自签名的(很可能)或过期等。

If this Jira instance is on-premise (hosted by your company) then having a self-signed certificate is not at all unlikely. In this case the certificate is not issued by a known CA, so if you wish to trust it, you need to manually register it.

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

First obtain the certificate:

首先获取证书:

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

Then import it into your own keystore:

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

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

Note: the commands above are for Unix environment. Under Windows I would suggest using similarly openssl from command line, but there are also GUI tools available for the same purpose.

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

回答by TomyDev

You can Replace

你可以更换

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

with

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

回答by 0x7E1

Check if the file $JAVA_HOME/lib/security/cacertsexists! In my case it was not a file but a link to /etc/ssl/certs/java/cacertsand also this was a link to itself (WHAT???) so due to it JVM can't find the file.

检查文件是否$JAVA_HOME/lib/security/cacerts存在!在我的情况下,它不是一个文件,而是一个链接,/etc/ssl/certs/java/cacerts这也是一个到它自己的链接(什么???),因此JVM找不到该文件。

Solution:Copy the real cacerts file (I did it from another JDK) to /etc/ssl/certs/java/directory and it'll solve your problem :)

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

回答by AguThadeus

If you are still facing issues with certificates even after importing the certificate as indicated by @Gergely Bacsothen make sure that the java.exe or javaw.exe binaries you have linked to your IDE or in your command line used to run your Java application are those from JRE not the JDK, I got certificate errors even after installing the certificate in cacertskeystore until I realised the binaries I was using were from the JDK. After I switched path to JRE everything went as expected and I was able to connect successfully. I hope it saves someone's time trying to debug the problem.

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