可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Edit :- Tried to format the question and accepted answer in more presentable way at mine Blog
Here is the original issue:-
I am getting this error
detailed message sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
cause 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
i am using tomcat 6 as webserver. i have two https webbapplication installed on different tomcat on differte port but on same machine. Say App1(port 8443)
and App2(port 443)
. App1
connects to App2
.When App1
connects to App2 i
get above error. I know this is very common error so came across many solutions on different forums and sites. I have below entry in server.xml
of both tomcat i.e
keystoreFile="c:/.keystore" keystorePass="changeit"
Every site says the same reason that certificate given by app2 is not in the trusted store of app1 jvm. This seems to be true also when i tired to hit the same URL in IE browser, it works(with warming, There is a problem with this web site's security certificate. here i say continue to this website) But when same url is hit by java client(in my case). So i get the above error. So to put it in trustore i tried these tree options i.e
Option1
System.setProperty("javax.net.ssl.trustStore", "C:/.keystore"); System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
Option2 Setting below in environment variable
CATALINA_OPTS -- param name -Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value
Option3 Setting below in environment variable
JAVA_OPTS -- param name -Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value
But nothing worked .
What at last worked is executing the java approach suggested in How to handle invalid SSL certificates with Apache HttpClient? by Pascal Thivent i.e executing the program InstallCert.
But this approach is fine for devbox setup but i can not use it at production environment.
I am wondering why three approaches mentioned above did not work when i have mentioned same values in server.xml
of app2
server and same values in truststore by setting
System.setProperty("javax.net.ssl.trustStore", "C:/.keystore") and System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
in app1
program.
For more information this is how i am making the connection
URL url = new URL(urlStr); URLConnection conn = url.openConnection(); if (conn instanceof HttpsURLConnection) { HttpsURLConnection conn1 = (HttpsURLConnection) url.openConnection(); conn1.setHostnameVerifier(new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); reply.load(conn1.getInputStream());
回答1:
You need to add the certificate for App2 to the truststore file of the used JVM located at %JAVA_HOME%\lib\security\cacerts
.
First you can check if your certificate is already in the truststore by running the following command: keytool -list -keystore "%JAVA_HOME%/jre/lib/security/cacerts"
(you don't need to provide a password)
If your certificate is missing, you can get it by downloading it with your browser and add it to the truststore with the following command:
keytool -import -noprompt -trustcacerts -alias -file -keystore -storepass
Afer import you can run the first command again to check if your certificate was added.
Sun/Oracle information can be found here.
回答2:
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
Base64 (.cer) format. It will be saved on your Desktop.
Now I had to make my java version to know about the certificate so that further it doesn’t refuse to recognize the URL. In this respect I must mention that I googled out that root certificate information stays by default in JDK’s \jre\lib\security location, and the default password to access is: changeit.
To view the cacerts information the following are the procedures to follow:
Java/jreX/bin
directory
keytool -list -keystore D:\Java\jdk1.5.0_12\jre\lib\security\cacerts
It gives the list of the current certificates contained within the keystore. It looks something like this:
C:\Documents and Settings\NeelanjanaG>keytool -list -keystore D:\Java\jdk1.5.0_12\jre\lib\security\cacerts
Enter keystore password: changeit
Keystore type: jks
Keystore provider: SUN
Your keystore contains 44 entries
verisignclass3g2ca, Mar 26, 2004, trustedCertEntry,
Certificate fingerprint (MD5): A2:33:9B:4C:74:78:73:D4:6C:E7:C1:F3:8D:CB:5C:E9
entrustclientca, Jan 9, 2003, trustedCertEntry,
Certificate fingerprint (MD5): 0C:41:2F:13:5B:A0:54:F5:96:66:2D:7E:CD:0E:03:F4
thawtepersonalbasicca, Feb 13, 1999, trustedCertEntry,
Certificate fingerprint (MD5): E6:0B:D2:C9:CA:2D:88:DB:1A:71:0E:4B:78:EB:02:41
addtrustclass1ca, May 1, 2006, trustedCertEntry,
Certificate fingerprint (MD5): 1E:42:95:02:33:92:6B:B9:5F:C0:7F:DA:D6:B2:4B:FC
verisignclass2g3ca, Mar 26, 2004, trustedCertEntry,
Certificate fingerprint (MD5): F8:BE:C4:63:22:C9:A8:46:74:8B:B8:1D:1E:4A:2B:F6
If you are using Java 7:
It is the solution I found for the Exception mentioned above!!
回答3:
How to work-it in Tomcat 7
I wanted to support a self signed certificate in a Tomcat App but the following snippet failed to work
import java.io.DataOutputStream; import java.net.HttpURLConnection; import java.net.URL; public class HTTPSPlayground { public static void main(String[] args) throws Exception { URL url = new URL("https:// ... .com"); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setRequestMethod("POST"); httpURLConnection.setRequestProperty("Accept-Language", "en-US,en;q=0.5"); httpURLConnection.setDoOutput(true); DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream()); String serializedMessage = "{}"; wr.writeBytes(serializedMessage); wr.flush(); wr.close(); int responseCode = httpURLConnection.getResponseCode(); System.out.println(responseCode); } }
this is what solved my issue:
1) Download the .crt
file
echo -n | openssl s_client -connect :443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/.crt
- replace
with your domain (e.g. jossef.com
)
2) Apply the .crt
file in Java's cacerts
certificate store
keytool -import -v -trustcacerts -alias -file ~/.crt -keystore /jre/lib/security/cacerts -keypass changeit -storepass changeit
- replace
with your domain (e.g. jossef.com
) - replace
with your java home directory
3) Hack it
Even though iv'e installed my certificate in Java
's default certificate stores, Tomcat ignores that (seems like it's not configured to use Java's default certificate stores).
To hack this, add the following somewhere in your code:
String certificatesTrustStorePath = "/jre/lib/security/cacerts"; System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath); // ...
回答4:
My cacerts file was totally empty. I solved this by copying the cacerts file off my windows machine (that's using Oracle Java 7) and scp'd it to my Linux box (OpenJDK).
cd %JAVA_HOME%/jre/lib/security/ scp cacerts mylinuxmachin:/tmp
and then on the linux machine
cp /tmp/cacerts /etc/ssl/certs/java/cacerts
It's worked great so far.
回答5:
For me, this error appeared too while trying to connect to a process behind an NGINX reverse proxy which was handling the SSL.
It turned out the problem was a certificate without the entire certificate chain concatenated. When I added intermediate certs, the problem was solved.
Hope this helps.
回答6:
For Tomcat running on Ubuntu server, to find out which Java is being used, use "ps -ef | grep tomcat" command:
Sample:
/home/mcp01$ **ps -ef |grep tomcat** tomcat7 28477 1 0 10:59 ? 00:00:18 **/usr/local/java/jdk1.7.0_15/bin/java** -Djava.util.logging.config.file=/var/lib/tomcat7/conf/logging.properties -Djava.awt.headless=true -Xmx512m -XX:+UseConcMarkSweepGC -Djava.net.preferIPv4Stack=true -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/share/tomcat7/endorsed -classpath /usr/share/tomcat7/bin/bootstrap.jar:/usr/share/tomcat7/bin/tomcat-juli.jar -Dcatalina.base=/var/lib/tomcat7 -Dcatalina.home=/usr/share/tomcat7 -Djava.io.tmpdir=/tmp/tomcat7-tomcat7-tmp org.apache.catalina.startup.Bootstrap start 1005 28567 28131 0 11:34 pts/1 00:00:00 grep --color=auto tomcat
Then, we can go in to: cd /usr/local/java/jdk1.7.0_15/jre/lib/security
Default cacerts file is located in here. Insert the untrusted certificate into it.
回答7:
Using Tomcat 7 under Linux, this did the trick.
String certificatesTrustStorePath = "/etc/alternatives/jre/lib/security/cacerts"; System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath); System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
Under Linux, $JAVA_HOME
is not always setup, but usually /etc/alternatives/jre
points to $JAVA_HOME/jre
回答8:
i wrote a small win32 (WinXP 32bit testet) stupid cmd (commandline) script which looks for all java versions in program files and adds a cert to them. The Password needs to be the default "changeit" or change it yourself in the script :-)
@echo off for /F %%d in ('dir /B %ProgramFiles%\java') do ( %ProgramFiles%\Java\%%d\bin\keytool.exe -import -noprompt -trustcacerts -file some-exported-cert-saved-as.crt -keystore %ProgramFiles%\Java\%%d\lib\security\cacerts -storepass changeit ) pause
回答9:
I have this problem too.
I tried almost everything by adding the SSL cert to .keystore, but, it was not working with Java1_6_x. For me it helped if we start using newer version of Java, Java1_8_x as JVM.
回答10:
Its a flaw of Java not using the standard Operating system keystore like in MacOS X. I filed a change request today see http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8185892
回答11:
Another reason could be an outdated version of JDK. I was using jdk version 1.8.0_60, simply updating to the latest version solved the certificate issue.