تحرير: - حاول تنسيق السؤال والإجابة المقبولة بطريقة أكثر ملاءمة في منجممدونة
هنا هي القضية الأصلية.
سأتعامل مع هذا الخطأ:
رسالة مفصلة Sun.security.validator.ValidatorException: فشل بناء مسار PKIX:
Sun.security.provider.certpath.SunCertPathBuilderException: غير قادر على العثور على مسار شهادة صالح إلى الهدف المطلوبتسبب javax.net.ssl.SSLHandshakeException: Sun.security.validator.ValidatorException: فشل بناء مسار PKIX: Sun.security.provider.certpath.SunCertPathBuilderException: غير قادر على العثور على مسار شهادة صالح إلى الهدف المطلوب
أنا أستخدم Tomcat 6 كملقم ويب. لديّ تطبيقان على شبكة HTTPS مثبتان على Tomcats مختلفين على منافذ مختلفة ولكن على نفس الجهاز. قل App1(port 8443)
و App2(port 443)
. App1
يتصل بـ App2
. عندما يتصل App1
بـ App2
أحصل على الخطأ أعلاه. أعرف أن هذا خطأ شائع جدًا ، لذا فقد واجهت العديد من الحلول في المنتديات والمواقع المختلفة. لدي الإدخال التالي في server.xml
لكلا Tomcats:
keystoreFile="c:/.keystore"
keystorePass="changeit"
يقول كل موقع نفس السبب في أن الشهادة المقدمة من app2 ليست في المتجر الموثوق به لـ app1 jvm. يبدو هذا صحيحًا أيضًا عندما حاولت الوصول إلى نفس عنوان URL في متصفح IE ، إنه يعمل (مع ارتفاع درجات الحرارة ، هناك مشكلة في شهادة أمان موقع الويب هذا ، وأقول هنا تابع إلى هذا الموقع). ولكن عندما يتم ضرب URL نفسه بواسطة عميل Java (في حالتي) ، تظهر لي الخطأ أعلاه. لذلك لوضعها في truststore جربت هذه الخيارات الثلاثة:
الخيار 1
System.setProperty("javax.net.ssl.trustStore", "C:/.keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
Option2 الإعداد أدناه في متغير البيئة
CATALINA_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value
Option3 الإعداد أدناه في متغير البيئة
Java_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value
ولكن لا شيء يعمل .
ما الذي حدث أخيرًا يتم تنفيذ منهج Java المقترح في كيفية التعامل مع شهادات SSL غير الصالحة باستخدام Apache HttpClient؟ بواسطة Pascal Thivent ، أي تنفيذ برنامج InstallCert.
ولكن هذا النهج جيد لإعداد devbox لكن لا يمكنني استخدامه في بيئة الإنتاج.
أتساءل لماذا لم تنجح الطرق الثلاثة المذكورة أعلاه عندما ذكرت نفس القيم في server.xml
لخادم app2
ونفس القيم في truststore عن طريق إعداد
System.setProperty("javax.net.ssl.trustStore", "C:/.keystore") and System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
في app1
البرنامج.
لمزيد من المعلومات ، هذه هي الطريقة التي أجري بها الاتصال:
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());
تحتاج إلى إضافة الشهادة لـ App2 إلى ملف truststore الخاص بـ JVM المستخدم الموجود في %Java_HOME%\lib\security\cacerts
.
أولاً ، يمكنك التحقق مما إذا كانت شهادتك موجودة بالفعل في متجر truststore من خلال تشغيل الأمر التالي: keytool -list -keystore "%Java_HOME%/jre/lib/security/cacerts"
(لست بحاجة إلى تقديم كلمة مرور)
إذا كانت شهادتك مفقودة ، فيمكنك الحصول عليها عن طريق تنزيلها مع متصفحك وإضافتها إلى موقع truststore باستخدام الأمر التالي:
keytool -import -noprompt -trustcacerts -alias <AliasName> -file <certificate> -keystore <KeystoreFile> -storepass <Password>
بعد الاستيراد ، يمكنك تشغيل الأمر الأول مرة أخرى للتحقق من إضافة شهادتك.
الشمس/معلومات أوراكل يمكن العثور عليها هنا .
javax.net.ssl.SSLHandshakeException: Sun.security.validator.ValidatorException: فشل بناء مسار PKIX: Sun.security.provider.certpath.SunCertPathBuilderException: غير قادر على العثور على مسار شهادة صالح إلى الهدف المطلوب
• عندما تلقيت الخطأ ، حاولت أن أحذف Google معنى التعبير ووجدت أن هذه المشكلة تحدث عندما يغيّر خادم شهادة HTTPS SSL ، ولا يتعرف إصدارنا الأقدم من Java على المرجع المصدق للشهادة (CA) .
• إذا كان بإمكانك الوصول إلى عنوان URL HTTPS في متصفحك ، فمن الممكن تحديث Java للتعرف على المرجع المصدق الجذر.
• في المستعرض الخاص بك ، انتقل إلى عنوان URL HTTPS الذي تعذر على Java الوصول إليه. انقر فوق سلسلة شهادات HTTPS (يوجد رمز قفل في Internet Explorer) ، انقر فوق القفل لعرض الشهادة.
• انتقل إلى "تفاصيل" الشهادة و "نسخ إلى ملف". انسخه في Base64 (.cer) التنسيق. سيتم حفظه على سطح المكتب الخاص بك.
• تثبيت الشهادة تجاهل جميع التنبيهات.
• هذه هي الطريقة التي جمعت بها معلومات الشهادة الخاصة بعنوان URL الذي كنت أحاول الوصول إليه.
الآن اضطررت إلى إنشاء إصدار Java الخاص بي لمعرفة الشهادة حتى لا يرفض التعرف على عنوان URL. في هذا الصدد ، يجب أن أذكر أنني خرجت من معلومات شهادة الجذر هذه بشكل افتراضي في JDK’s\jre\lib\security الموقع ، وكلمة المرور الافتراضية للوصول هي: changeit.
لعرض معلومات cacerts فيما يلي الإجراءات الواجب اتباعها:
• انقر فوق زر ابدأ -> تشغيل
• اكتب كمد. يتم فتح موجه الأوامر (قد تحتاج إلى فتحه كمسؤول).
• انتقل إلى دليل Java/jreX/bin
الخاص بك
• اكتب ما يلي
keytool -list -keystore D:\Java\jdk1.5.0_12\jre\lib\security\cacerts
أنه يعطي قائمة الشهادات الحالية الموجودة داخل لوحة المفاتيح. يبدو شيء مثل هذا:
C:\Documents and Settings\NeelanjanaG> keytool -list -keystore D:\Java\jdk1.5.0_12\jre\lib\security\cacerts
أدخل كلمة السر الرئيسية: changeit
نوع المفتاح: jks
موفر المفاتيح: أحد
يحتوي مفتاحك على 44 مُدخلاً
verisignclass3g2ca ، 26 مارس 2004 ، TrustedCertEntry ،
بصمة الشهادة (MD5): A2: 33: 9B: 4C: 74: 78: 73: D4: 6C: E7: C1: F3: 8D: CB: 5C: E9
entrustclientca ، ٩ يناير ٢٠٠٣ ، TrustedCertEntry ،
بصمة الشهادة (MD5): 0C: 41: 2F: 13: 5B: A0: 54: F5: 96: 66: 2D: 7E: CD: 0E: 03: F4
thawtepersonalbasicca ، 13 فبراير 1999 ، TrustedCertEntry ،
بصمة الشهادة (MD5): E6: 0B: D2: C9: CA: 2D: 88: DB: 1A: 71: 0E: 4B: 78: EB: 02: 41
addtrustclass1ca ، 1 مايو ، 2006 ، TrustedCertEntry ،
بصمة الشهادة (MD5): 1E: 42: 95: 02: 33: 92: 6B: B9: 5F: C0: 7F: DA: D6: B2: 4B: FC
verisignclass2g3ca ، 26 مارس 2004 ، TrustedCertEntry ،
بصمة الشهادة (MD5): F8: BE: C4: 63: 22: C9: A8: 46: 74: 8B: B8: 1D: 1E: 4A: 2B: F6
• الآن اضطررت إلى تضمين الشهادة المثبتة مسبقًا في cacerts.
• فيما يلي الإجراء:
keytool –import –noprompt –trustcacerts -alias ALIASNAME -file FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass PASSWORD
إذا كنت تستخدم Java 7:
keytool –importcert –trustcacerts -alias ALIASNAME -file PATH_TO_FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE - changeorestit
• سيقوم بعد ذلك بإضافة معلومات الشهادة إلى ملف cacert.
هذا هو الحل الذي وجدته للاستثناء المذكور أعلاه !!
كنت أرغب في دعم شهادة موقعة ذاتيًا في تطبيق Tomcat ولكن فشل القصاصة التالية في العمل
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);
}
}
هذا هو ما حل مشكلتي:
.crt
echo -n | openssl s_client -connect <your domain>:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/<your domain>.crt
<your domain>
بنطاقك (على سبيل المثال ، jossef.com
).crt
في متجر شهادات cacerts
الخاص بجافاkeytool -import -v -trustcacerts -alias <your domain> -file ~/<your domain>.crt -keystore <Java HOME>/jre/lib/security/cacerts -keypass changeit -storepass changeit
<your domain>
بنطاقك (على سبيل المثال ، jossef.com
)<Java HOME>
بدليل Java الرئيسيعلى الرغم من أن iv'e قد قمت بتثبيت شهادتي في مخازن الشهادات الافتراضية Java
، يتجاهل Tomcat ذلك (يبدو أنه لم تتم تهيئته لاستخدام مخازن شهادات Java الافتراضية).
لاختراق هذا ، أضف ما يلي في مكان ما في الكود:
String certificatesTrustStorePath = "<Java HOME>/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);
// ...
في حالتي ، كانت المشكلة هي أن خادم الويب كان يرسل الشهادة فقط و المرجع المصدق الوسيط ، وليس المرجع المصدق الجذر. إضافة خيار JVM هذا حل المشكلة: -Dcom.Sun.security.enableAIAcaIssuers=true
يتوفر دعم لطريقة وصول caIssuers لملحق وصول معلومات السلطة. يتم تعطيله افتراضيًا للتوافق ويمكن تمكينه عن طريق تعيين خاصية النظام
com.Sun.security.enableAIAcaIssuers
إلى القيمة الحقيقية.إذا تم التعيين على true ، فإن تطبيق PKIX الخاص بـ Sun's لـ CertPathBuilder يستخدم المعلومات في ملحق AIA الخاص بالشهادة (بالإضافة إلى CertStores المحددة) للعثور على شهادة المرجع المصدق المصدرة ، شريطة أن يكون URI من النوع ldap أو http أو ftp.
ملف cacerts الخاص بي كان فارغًا تمامًا. لقد قمت بحل هذا عن طريق نسخ ملف cacerts من جهاز windows الخاص بي (والذي يستخدم Oracle Java 7) وقمت بمراقبته إلى صندوق Linux الخاص بي (OpenJDK).
cd %Java_HOME%/jre/lib/security/
scp cacerts mylinuxmachin:/tmp
ثم على آلة لينكس
cp /tmp/cacerts /etc/ssl/certs/Java/cacerts
إنه عمل رائع حتى الآن.
سبب آخر يمكن أن يكون إصدار قديم من JDK. كنت تستخدم jdk الإصدار 1.8.0_60 ، مجرد تحديث إلى أحدث إصدار حل مشكلة الشهادة.
باستخدام Tomcat 7 في نظام Linux ، فعلت هذه الحيلة.
String certificatesTrustStorePath = "/etc/alternatives/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
ضمن Linux ، لا يتم دائمًا إعداد $Java_HOME
، لكن عادةً /etc/alternatives/jre
يشير إلى $Java_HOME/jre
بالنسبة لي ، ظهر هذا الخطأ أيضًا أثناء محاولة الاتصال بعملية وراء وكيل NGINX العكسي الذي كان يتعامل مع SSL.
اتضح أن المشكلة كانت شهادة بدون سلسلة الشهادة بأكملها متسلسلة. عندما أضفت certs المتوسطة ، تم حل المشكلة.
أتمنى أن يساعدك هذا.
كنت أستخدم jdk1.8.0_171
عندما واجهت نفس المشكلة. جربت أفضل الحلول 2 هنا (إضافة شهادة باستخدام keytool والحل الآخر الذي يحتوي على اختراق) ، لكنهم لم يعملوا من أجلي.
لقد قمت بترقية JDK إلى 1.8.0_181
وكان يعمل مثل السحر.
أدناه رمز يعمل بالنسبة لي:
import Java.security.cert.CertificateException;
import Java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
public class TrustAnyTrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] {};
}
}
HttpsURLConnection conn = null;
URL url = new URL(serviceUrl);
conn = (HttpsURLConnection) url.openConnection();
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new Java.security.SecureRandom());
conn.setSSLSocketFactory(sc.getSocketFactory());
كتبت برنامج نصي صغير Win32 (WinXP 32bit testet) غبي كمد (سطر الأوامر) الذي يبحث عن جميع إصدارات جافا في ملفات البرنامج ويضيف سيرت لهم. يجب أن تكون كلمة المرور هي "changeit" الافتراضي أو قم بتغييرها بنفسك في البرنامج النصي :-)
@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
لتشغيل Tomcat على خادم Ubuntu ، لمعرفة أي Java قيد الاستخدام ، استخدم أمر "ps -ef | grep Tomcat":
عينة:
/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
بعد ذلك ، يمكننا الدخول إلى: cd /usr/local/Java/jdk1.7.0_15/jre/lib/security
الافتراضي cacerts الملف موجود هنا. أدخل الشهادة غير الموثوق بها.
انا أيضا لدي هذه المشكلة.
جربت كل شيء تقريبًا عن طريق إضافة شهادة SSL إلى .keystore ، لكن لم تكن تعمل مع Java1_6_x. بالنسبة لي ، لقد ساعدنا ذلك إذا بدأنا في استخدام الإصدار الأحدث من Java ، Java1_8_x كـ JVM.
بالنسبة لنظام التشغيل MacOS X أدناه ، تم تنفيذ الأمر الدقيق لي حيث اضطررت لمحاولة استخدام الواصلة المزدوجة في خيار "importcert" الذي نجح:
Sudo keytool -–importcert -file /PathTo/YourCertFileDownloadedFromBrowserLockIcon.crt -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/security/cacerts -alias "Cert" -storepass changeit
من أجل السلامة ، يجب ألا نستخدم الشهادات الموقعة ذاتيا في تطبيقنا. ومع ذلك ، عندما يتعلق الأمر بالتطوير في كثير من الأحيان ، يتعين علينا استخدام البيئات التجريبية التي حصلت على توقيعات ذاتية. حاولت إصلاح هذه المشكلة برمجيًا في الكود وفشلت. ومع ذلك ، من خلال إضافة cert إلى jre trust-store ، حل مشكلتي. تجدون أدناه الخطوات ،
تحميل الموقع سيرت ،
انسخ الشهادة (على سبيل المثال: cert_file.cer) إلى الدليل $ Java_HOME\Jre\Lib\Security
افتح CMD في المسؤول وقم بتغيير الدليل إلى $ Java_HOME\Jre\Lib\Security
استيراد الشهادة إلى متجر موثوق باستخدام الأمر أدناه ،
keytool -import -alias ca -file cert_file.cer -cystations cacerts -storepass changeit
(إذا حصلت على خطأ يقول أن أداة المفاتيح غير معروفة ، فيرجى راجع هذا.
اكتب نعم مثل أدناه
الوثوق بهذه الشهادة: [نعم]
تحديث
إذا كان خادم التطبيق الخاص بك هو jboss ، فجرّب إضافة خاصية النظام أدناه
System.setProperty("org.jboss.security.ignoreHttpsHost","true");
أتمنى أن يساعدك هذا!
واجهت هذه المشكلة باستخدام AndroidStudio
و Charles Proxy
و JUnit
و Robolectric
. شكراSimonSez يمكنني حل المشكلة.
%Java_HOME%
- يستخدم Android JavaHome مختلفًا. يمكنك العثور على المسار الكامل في نافذة Run
UnitTests
. في حالتي ، /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home
Downloads
قم بتشغيل الأمر
Sudo keytool -import -noprompt -trustcacerts -alias charles -file ~/Downloads/charles-ssl-proxying-certificate.pem -keystore "/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/security/cacerts" -storepass changeit