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
Exception unable to validate certificate of the target in spring MVC
提问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/cacerts
exists!
In my case it was not a file but a link to /etc/ssl/certs/java/cacerts
and 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 cacerts
keystore 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 的路径后,一切都按预期进行,我能够成功连接。我希望它可以节省某人尝试调试问题的时间。