我正在尝试使用 twitter4j 库为我的 java 项目获取推文,该项目在 java.net.HttpURLConnection
下使用(如堆栈跟踪中所示)。在我第一次运行时,我收到关于证书 sun.security.validator.ValidatorException
和 sun.security.provider.certpath.SunCertPathBuilderException
的错误。然后我通过以下方式添加了 twitter 证书:
C:\Program Files\Java\jdk1.7.0_45\jre\lib\security>keytool -importcert -trustcacerts -file PathToCert -alias ca_alias -keystore "C:\Program Files\Java\jdk1.7.0_45\jre\lib\security\cacerts"
但没有成功。以下是获取推文的过程:
public static void main(String[] args) throws TwitterException {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
.setOAuthConsumerKey("myConsumerKey")
.setOAuthConsumerSecret("myConsumerSecret")
.setOAuthAccessToken("myAccessToken")
.setOAuthAccessTokenSecret("myAccessTokenSecret");
TwitterFactory tf = new TwitterFactory(cb.build());
Twitter twitter = tf.getInstance();
try {
Query query = new Query("iphone");
QueryResult result;
result = twitter.search(query);
System.out.println("Total amount of tweets: " + result.getTweets().size());
List<Status> tweets = result.getTweets();
for (Status tweet : tweets) {
System.out.println("@" + tweet.getUser().getScreenName() + " : " + tweet.getText());
}
} catch (TwitterException te) {
te.printStackTrace();
System.out.println("Failed to search tweets: " + te.getMessage());
}
这是错误:
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Relevant discussions can be found on the Internet at:
http://www.google.co.jp/search?q=d35baff5 or
http://www.google.co.jp/search?q=1446302e
TwitterException{exceptionCode=[d35baff5-1446302e 43208640-747fd158 43208640-747fd158 43208640-747fd158], statusCode=-1, message=null, code=-1, retryAfter=-1, rateLimitStatus=null, version=3.0.5}
at twitter4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:177)
at twitter4j.internal.http.HttpClientWrapper.request(HttpClientWrapper.java:61)
at twitter4j.internal.http.HttpClientWrapper.get(HttpClientWrapper.java:81)
at twitter4j.TwitterImpl.get(TwitterImpl.java:1929)
at twitter4j.TwitterImpl.search(TwitterImpl.java:306)
at jku.cc.servlets.TweetsAnalyzer.main(TweetsAnalyzer.java:38)
Caused by: 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
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
at sun.security.ssl.Handshaker.processLoop(Unknown Source)
at sun.security.ssl.Handshaker.process_record(Unknown Source)
at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at java.net.HttpURLConnection.getResponseCode(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(Unknown Source)
at twitter4j.internal.http.HttpResponseImpl.<init>(HttpResponseImpl.java:34)
at twitter4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:141)
... 5 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
at sun.security.validator.Validator.validate(Unknown Source)
at sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
... 20 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
at java.security.cert.CertPathBuilder.build(Unknown Source)
... 26 more
Failed to search tweets: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
在浏览器中转到 URL:
firefox - 单击 HTTPS 证书链(URL 地址旁边的锁定图标)。单击“更多信息”>“安全”>“显示证书”>“详细信息”>“导出..”。选择名称并选择文件类型 example.cer
chrome - 单击左侧的站点图标到地址栏中的地址,选择“证书”->“详细信息”->“导出”并以“Der-encoded binary, single certificate”格式保存。
现在您有了带有密钥库的文件,您必须将它添加到您的 JVM。确定 cacerts 文件的位置,例如。 C:\Program 文件 (x86)\Java\jre1.6.0_22\lib\security\cacerts。接下来在命令行中将 example.cer 文件导入 cacerts(可能需要管理员命令提示符):
keytool -import -alias example -keystore "C:\Program Files (x86)\Java\jre1.6.0_22\lib\security\cacerts" -file example.cer
您将被要求输入密码,默认为 changeit
重新启动您的 JVM/PC。
来源:http://magicmonster.com/kb/prg/java/ssl/pkix_path_building_failed.html
在尝试构建证书文件以使我的 Java 6 安装与新的 twitter 证书一起工作数小时后,我终于偶然发现了一个非常简单的解决方案,隐藏在其中一个留言板的评论中。只需从 Java 7 安装复制 cacerts 文件并覆盖 Java 6 安装中的文件。最好先备份 cacerts 文件,然后您只需将新文件复制进去,然后 BOOM!它只是工作。
请注意,我实际上将一个 Windows cacerts 文件复制到了 Linux 安装中,它工作得很好。
在新旧 Java jdk 安装中,该文件都位于 jre/lib/security/cacerts
中。
希望这可以为其他人节省数小时的恶化时间。
$JAVA_HOME/jre/lib
,而不是 $JAVA_HOME/lib
——我花了一些时间错过了那个细节。
我的用户界面方法:
从这里下载密钥库资源管理器 打开 $JAVA_HOME/jre/lib/security/cacerts 输入密码:changeit(在 Mac 上可以是 changeme) 导入您的 .crt 文件
CMD-行:
keytool -importcert -file jetty.crt -alias jetty -keystore $JAVA_HOME/jre/lib/security/cacerts 输入密码:changeit(Mac上可以是changeme)
keytool -importcert -file dinardap_cert.cer –alias dinardap –keystore “%JAVA_HOME%/jre/lib/security/cacerts”
1.检查证书
尝试在浏览器中加载目标 URL 并查看站点的证书(通常可以通过带有锁定符号的图标访问。它位于浏览器地址栏的左侧或右侧)是否已过期或因其他原因不受信任。
2.安装最新版本的JRE和JDK
新版本通常带有更新的可信证书集。
另外,如果可能,请卸载旧版本。这将使错误配置错误明确。
3. 检查您的配置:
检查您的 JAVA_HOME 环境变量指向的位置。
检查您用于运行程序的 java 版本。在 IntelliJ 检查:文件 -> 项目结构... -> 项目设置 -> 项目 -> 项目 SDK:文件 -> 项目结构... -> 平台设置 -> SDK
文件 -> 项目结构... -> 项目设置 -> 项目 -> 项目 SDK:
文件 -> 项目结构... -> 平台设置 -> SDK
4. 从新的 Java 版本复制整个密钥库
如果您在 JDK 而非最新可用的 JDK 下进行开发 - 请尝试使用最新安装的 JRE 中的新文件替换 %JAVA_HOME%/jre/lib/security/cacerts
文件(首先制作备份副本),正如 @jeremy-goodell 在他的 answer 中所建议的那样
5. 将证书添加到您的密钥库
如果以上都不能解决您的问题,请使用 keytool
将证书保存到 Java 的密钥库:
keytool -trustcacerts -keystore "%JAVA_HOME%jre\lib\security\cacerts" -storepass changeit -importcert -alias <alias_name> -file <path_to_crt_file>
正如@MagGGG 在他的answer 中建议的那样,可以从浏览器中获取带有证书的文件。
注意 1:您可能需要对链中的每个证书重复此操作,以至您的站点证书。从根开始。
注意 2:<alias_name>
在 store 中的键中应该是唯一的,否则 keytool
将显示错误。
要获取商店中所有证书的列表,您可以运行:
keytool -list -trustcacerts -keystore "%JAVA_HOME%jre\lib\security\cacerts" -storepass changeit
如果出现问题,这将帮助您从商店中删除证书:
keytool -delete -alias <alias_name> -keystore "%JAVA_HOME%jre\lib\security\cacerts" -storepass changeit
keytool -list -trustcacerts -keystore "$JAVA_HOME/jre/lib/security/cacerts" -storepass changeit
-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true
它用于跳转证书验证。
警告仅用于开发目的是不安全的!
我偶然发现了这个问题,该问题需要花费数小时的研究才能解决,特别是使用自动生成的证书,与官方证书不同,它非常棘手,Java 不太喜欢它们。
请检查以下链接:Solve Problem with certificates in Java
基本上,您必须将证书从服务器添加到 Java Home 证书。
生成或获取您的证书并配置 Tomcat 以在 Servers.xml 中使用它 下载 InstallCert 类的 Java 源代码并在服务器运行时执行它,提供以下参数 server[:port]。不需要密码,因为原始密码适用于 Java 证书(“changeit”)。程序将连接到服务器,Java 将抛出异常,它将分析服务器提供的证书,并允许您在执行程序的目录中创建一个 jssecerts 文件(如果从 Eclipse 执行,请确保配置运行 -> 配置中的工作目录)。手动将该文件复制到 $JAVA_HOME/jre/lib/security
执行这些步骤后,与证书的连接将不再在 Java 中生成异常。
以下源代码很重要,它从(Sun)Oracle 博客中消失了,我发现它的唯一页面是在提供的链接上,因此我将其附在答案中以供参考。
/*
* Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Sun Microsystems nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Originally from:
* http://blogs.sun.com/andreas/resource/InstallCert.java
* Use:
* java InstallCert hostname
* Example:
*% java InstallCert ecc.fedora.redhat.com
*/
import javax.net.ssl.*;
import java.io.*;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* Class used to add the server's certificate to the KeyStore
* with your trusted certificates.
*/
public class InstallCert {
public static void main(String[] args) throws Exception {
String host;
int port;
char[] passphrase;
if ((args.length == 1) || (args.length == 2)) {
String[] c = args[0].split(":");
host = c[0];
port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
String p = (args.length == 1) ? "changeit" : args[1];
passphrase = p.toCharArray();
} else {
System.out.println("Usage: java InstallCert [:port] [passphrase]");
return;
}
File file = new File("jssecacerts");
if (file.isFile() == false) {
char SEP = File.separatorChar;
File dir = new File(System.getProperty("java.home") + SEP
+ "lib" + SEP + "security");
file = new File(dir, "jssecacerts");
if (file.isFile() == false) {
file = new File(dir, "cacerts");
}
}
System.out.println("Loading KeyStore " + file + "...");
InputStream in = new FileInputStream(file);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(in, passphrase);
in.close();
SSLContext context = SSLContext.getInstance("TLS");
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
context.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory factory = context.getSocketFactory();
System.out.println("Opening connection to " + host + ":" + port + "...");
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
socket.setSoTimeout(10000);
try {
System.out.println("Starting SSL handshake...");
socket.startHandshake();
socket.close();
System.out.println();
System.out.println("No errors, certificate is already trusted");
} catch (SSLException e) {
System.out.println();
e.printStackTrace(System.out);
}
X509Certificate[] chain = tm.chain;
if (chain == null) {
System.out.println("Could not obtain server certificate chain");
return;
}
BufferedReader reader =
new BufferedReader(new InputStreamReader(System.in));
System.out.println();
System.out.println("Server sent " + chain.length + " certificate(s):");
System.out.println();
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
MessageDigest md5 = MessageDigest.getInstance("MD5");
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = chain[i];
System.out.println
(" " + (i + 1) + " Subject " + cert.getSubjectDN());
System.out.println(" Issuer " + cert.getIssuerDN());
sha1.update(cert.getEncoded());
System.out.println(" sha1 " + toHexString(sha1.digest()));
md5.update(cert.getEncoded());
System.out.println(" md5 " + toHexString(md5.digest()));
System.out.println();
}
System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
String line = reader.readLine().trim();
int k;
try {
k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
} catch (NumberFormatException e) {
System.out.println("KeyStore not changed");
return;
}
X509Certificate cert = chain[k];
String alias = host + "-" + (k + 1);
ks.setCertificateEntry(alias, cert);
OutputStream out = new FileOutputStream("jssecacerts");
ks.store(out, passphrase);
out.close();
System.out.println();
System.out.println(cert);
System.out.println();
System.out.println
("Added certificate to keystore 'jssecacerts' using alias '"
+ alias + "'");
}
private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
private static String toHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 3);
for (int b : bytes) {
b &= 0xff;
sb.append(HEXDIGITS[b >> 4]);
sb.append(HEXDIGITS[b & 15]);
sb.append(' ');
}
return sb.toString();
}
private static class SavingTrustManager implements X509TrustManager {
private final X509TrustManager tm;
private X509Certificate[] chain;
SavingTrustManager(X509TrustManager tm) {
this.tm = tm;
}
public X509Certificate[] getAcceptedIssuers() {
throw new UnsupportedOperationException();
}
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
throw new UnsupportedOperationException();
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
this.chain = chain;
tm.checkServerTrusted(chain, authType);
}
}
}
SandeepanNath:test sandeepan.nath$ java InstallCert repo1.maven.org:443 Loading KeyStore /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home/jre/lib/security/cacerts... Opening connection to repo1.maven.org:443 ... Starting SSL handshake... javax.net.ssl.SSLException: Received fatal alert: protocol_version .. Could not obtain server certificate chain
苹果电脑
接受的答案不适用于 Mac,因为 Mac(Chrome 或 Firefox)中没有 Export 按钮。请勾选 this answer 下载证书并按照以下步骤进行操作:
列出密钥库中安装的所有证书:
cd $JAVA_HOME/lib/security
keytool -list -keystore cacerts
笔记:
密钥库的默认密码是:changeit。
对于 Java-8 或更低版本,请使用命令 cd $JAVA_HOME/jre/lib/security
在将证书导入密钥库之前,请备份密钥库:
sudo cp cacerts cacerts.bak
在密钥库中导入下载的证书:
sudo keytool -importcert -alias youralias -file /path/to/the/downloaded/certificate -keystore cacerts
检查证书是否存储在密钥库中:
sudo keytool -list -keystore cacerts -alias youralias
如果您想查看更多详细信息,请添加 -v
标志:
sudo keytool -v -list -keystore cacerts -alias youralias
我想为 smtp.gmail.com
导入证书。唯一对我有用的解决方案是
输入命令查看此证书 D:\openssl\bin\openssl.exe s_client -connect smtp.gmail.com:465 复制并保存 -----BEGIN CERTIFICATE----- 和 ----- 之间的行END CERTIFICATE----- 放入文件,gmail.cer 运行 keytool -import -alias smtp.gmail.com -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -file C:\Users\Admin\Desktop \gmail.cer 输入密码:changeit 点击“是”导入证书 重启Java
现在运行命令,你就可以开始了。
当我的系统上同时存在 JDK 和 JRE 1.8.0_112 时,我的情况略有不同。
我使用已知命令将新 CA 证书导入 [JDK_FOLDER]\jre\lib\security\cacerts
:
keytool -import -trustcacerts -keystore cacerts -alias <new_ca_alias> -file <path_to_ca_cert_file>
尽管如此,我仍然收到相同的 PKIX 路径构建失败错误。
我使用 java -Djavax.net.debug=all ... > debug.log
将调试信息添加到 java CLI。在 debug.log 文件中,以 trustStore 开头的行是: 实际上指向在 [JRE_FOLDER]\lib\security\cacerts
中找到的 cacerts 存储。
在我的情况下,解决方案是将 JDK 使用的 cacerts 文件(添加了新的 CA)复制到 JRE 使用的文件上,从而解决了这个问题。
这不是特定于 Twitter 的答案,但这是您搜索此错误时出现的问题。如果您的系统在连接到在 Web 浏览器中查看时似乎具有有效证书的网站时收到此错误,这可能意味着该网站的证书链不完整。
对于问题的简要总结:证书颁发机构不使用他们的根证书来签署任何旧证书。相反,他们(通常)签署也设置了证书颁发机构标志的中间证书(即,允许签署证书)。然后,当您从 CA 购买证书时,他们会使用这些中间证书之一签署您的 CSR。
您的 Java 信任库很可能只有根证书,而不是中间证书。
配置错误的站点可能只返回他们签名的证书。问题:它是使用不在您的信任库中的中间证书签名的。浏览器将通过下载或使用缓存的中间证书来处理这个问题;这最大限度地提高了网站的兼容性。然而,Java 和 OpenSSL 等工具不会。这将导致问题中的错误。
您可以使用 Qualys SSL Test 验证此怀疑。如果你对一个网站运行它并且它说
此服务器的证书链不完整。
然后确认它。您还可以通过查看认证路径并查看文本额外下载来查看这一点。
如何解决:服务器管理员需要配置 Web 服务器以返回中间证书。例如,对于 Comodo,这就是 .ca-bundle
文件派上用场的地方。例如,在带有 mod_ssl 的 Apache 配置中,您将使用 SSLCertificateChainFile
配置设置。对于 nginx,您需要连接中间证书和签名证书,并在 SSL 证书配置中使用它。您可以通过在线搜索“不完整的证书链”找到更多信息。
问题背景:
当我尝试在我的项目中运行 mvn clean install 并通过 Netbeans IDE clean and build 选项运行时,我遇到了以下错误。此问题是由于当我们通过 NET beans IDE/通过命令提示符下载时证书不可用,但能够通过浏览器下载文件。
错误:
Caused by: org.eclipse.aether.transfer.ArtifactTransferException: Could not transfer artifact com.java.project:product:jar:1.0.32 from/to repo-local (https://url/local-repo): sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
解析度:
1.下载相关Url的证书:
通过“以管理员身份运行”启动 IE(否则,我们将无法下载证书)
在 IE-> https://url/local-repo 中输入 url(在我的例子中,这个 url 有一个不受信任的证书。)
通过单击证书错误->查看证书下载证书
选择详细信息选项卡 -> 复制到文件 -> 下一步 -> 选择“DER 编码二进制 X.509 (.CER)
将证书保存在某个位置,例如:c:/user/Sheldon/desktop/product.cer
恭喜!您已成功下载该站点的证书
2. 现在安装密钥库来解决问题。
运行 keytool 命令将下载的密钥库附加到现有证书文件中。
命令:jdk(JAVA_HOME)的bin文件夹中的以下命令。
C:\Program Files\Java\jdk1.8.0_141\jre\bin>keytool -importcert -file "C:/user/sheldon/desktop/product.cer" -alias product -keystore "C:/Program Files/Java/ jdk1.8.0_141/jre/lib/security/cacerts”。
系统将提示您输入密码。输入密钥库密码:“信任此证书?[否]:”再次输入“changeit”,输入“是”
示例命令行命令/输出:
keytool -importcert -file "C:/Users/sheldon/Desktop/product.cer" -alias product -keystore "C:/Program iles/Java/jdk1.8.0_141/jre/lib/security/cacerts"
Enter keystore password:
Trust this certificate? [no]: yes
Certificate was added to keystore
恭喜!现在您应该已经摆脱了 Netbeans IDE 中的“PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException”错误。
这是一个解决方案,但以我关于这个问题的故事的形式:
我几乎死了尝试上面给出的所有解决方案(3天),但对我没有任何帮助。
我失去了所有的希望。
我就此事联系了我的安全团队,因为我在代理背后,他们告诉他们最近更新了他们的安全策略。
我骂他们没有通知开发者。
后来他们发布了一个包含所有证书的新“cacerts”文件。
我删除了 %JAVA_HOME%/jre/lib/security 中存在的 cacerts 文件,它解决了我的问题。
因此,如果您面临这个问题,您的网络团队可能也会这样。
出现上述错误的原因是 JDK 与许多受信任的证书颁发机构 (CA) 证书捆绑到一个名为“cacerts”的文件中,但该文件不知道我们的自签名证书。换句话说,cacerts 文件没有导入我们的自签名证书,因此不会将其视为受信任的实体,因此会出现上述错误。
要修复上述错误,我们只需将自签名证书导入 cacerts 文件即可。
首先,找到 cacerts 文件。我们需要找出 JDK 的位置。如果您通过 Eclipse 或 IntelliJ Idea 等 IDE 之一运行应用程序,请转到项目设置并确定 JDK 位置。例如,在 Mac OS 上,cacerts 文件的典型位置将在此位置 /Library/Java/JavaVirtualMachines/ {{JDK_version}}/Contents/Home/jre/lib/security 在 Window 的机器上,它将位于 {{Installation_directory} }/{{JDK_version}}/jre/lib/security
一旦你找到了 cacerts 文件,现在我们需要将我们的自签名证书导入到这个 cacerts 文件中。如果不知道如何正确生成自签名证书,请查看上一篇文章。
如果您没有证书文件 (.crt) 而只有 .jks 文件,则可以使用以下命令生成 .crt 文件。如果您已经有一个 .crt/.pem 文件,那么您可以忽略以下命令
##从密钥库(.jks 文件)生成证书####
keytool -export -keystore keystore.jks -alias selfsigned -file selfsigned.crt
上述步骤将生成一个名为 selfsigned.crt 的文件。现在将证书导入 cacerts
keytool -importcert -file selfsigned.crt -alias selfsigned -keystore {{cacerts path}}
例如
keytool -importcert -file selfsigned.nextgen.crt -alias selfsigned.nextgen -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/cacerts
就是这样,重新启动您的应用程序,它应该可以正常工作。如果它仍然不起作用并获得 SSL 握手异常。这可能意味着您使用的是不同的域,然后在证书中注册。
链接 with detailed explanation and step by step resolution is over here.
挣扎了半天,又找到了解决这个问题的方法。我能够在 MAC 10.15.5(Catalina)中解决这个问题。遵循以下步骤。
当我们在公司代理后面运行时会出现此问题,在我的情况下是 Zscaler。
打开钥匙串访问,导出CA证书。(选择CA证书,文件->导出项目并使用所需名称保存)
从java文件夹复制现有cacerts的路径(/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/security/cacerts)
打开终端并导航到 Keytool 文件夹(/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/bin)
运行以下命令。
Keytool -importcert - 文件(从 keychainaccess 导出的证书的路径) -alias(命名) -keystore(来自 java 文件夹的现有 cacerts 的路径)
sudo Keytool -importcert -file /Users/Desktop/RootCA.cer -alias demo -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/security/cacerts
它会要求输入密码,给它:changeit
它要求确认,说:是
在所有这些步骤之后,退出 eclipse 和终端开始新的会话。
我遇到了同样的问题,并使用以下简单步骤解决了它:
1) 从谷歌下载 InstallCert.java
2) 使用 javac InstallCert.java 编译它
3) 使用 java InstallCert.java 运行 InstallCert.java,使用主机名和 https 端口,并在要求输入时按“1”。它将“localhost”添加为受信任的密钥库,并生成一个名为“jssecacerts”的文件,如下所示:
java InstallCert 本地主机:443
4) 将 jssecacerts 复制到 $JAVA_HOME/jre/lib/security 文件夹中
解决此问题的主要来源是:
https://ankurjain26.blogspot.in/2017/11/javaxnetsslsslhandshakeexception.html
添加 cacerts
对我不起作用。启用带有标志 -Djavax.net.debug=all
的日志后,就知道 java 从 jssecacerts
读取。
导入到 jssecacerts
终于奏效了。
jssecacerts
(如果存在),否则使用 cacerts
。
对我来说,出现证书错误是因为我让 fiddler 在后台运行并且这与证书混淆了。它充当代理,如此接近并重新启动 Eclipse。
我在尝试通过他们的更新站点在 Eclipse 中安装 Cucumber-Eclipse 插件时遇到了这个问题。我收到了同样的 SunCertPathBuilderException 错误:
Unable to read repository at http://cucumber.io/cucumber-eclipse/update-site/content.xml.
Unable to read repository at http://cucumber.io/cucumber-eclipse/update-site/content.xml.
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
虽然其他一些答案对于这个问题的给定情况是适当的和有帮助的,但它们对我的问题没有帮助和误导。
就我而言,问题在于为他们的更新站点提供的 URL 是:
https://cucumber.io/cucumber-eclipse/update-site
但是,当通过浏览器导航到它时,它会重定向到(注意添加的“.github”):
http://cucumber.github.io/cucumber-eclipse/update-site/
所以解决方法是在eclipse中添加更新站点时,简单的使用重定向版本的更新站点URL。
我通过将证书从 pkcs12
存储库导入到 cacerts
密钥库,在 Windows Server 2016 上使用 Java 8 解决了这个问题。
pkcs12 存储的路径:
C:\Apps\pkcs12.pfx
Java cacerts 的路径:
C:\Program Files\Java\jre1.8.0_151\lib\security\cacerts
keytool 的路径:
C:\Program Files\Java\jre1.8.0_151\bin
在命令提示符下(以管理员身份)使用 keytool 定位到文件夹后,将证书从 pkcs12
导入到 cacerts
的命令如下:
keytool -v -importkeystore -srckeystore C:\Apps\pkcs12.pfx -srcstoretype PKCS12 -destkeystore "C:\Program Files\Java\jre1.8.0_151\lib\security\cacerts" -deststoretype JKS
您将提示:
1. 输入目标密钥库密码(cacerts 密码,默认为“changeit”)
2. 输入源密钥库密码(pkcs12 密码)
要使更改生效,请重新启动服务器机器(或仅重新启动 JVM)。
C:\Program Files\Java\jdk1.8.0_281\jre\lib\security\cacerts
而不是 Java\jre1.8...
应该使用`Java\jdk1.8...\jre`
问题是,您的 Eclipse 无法连接它实际尝试连接的站点。我遇到了类似的问题,下面给出的解决方案对我有用。
关闭任何第三方互联网安全应用程序,例如 Zscaler,如果您已连接,有时还需要断开 VPN。
谢谢
目标:
使用 https 连接验证 SSL 链不处理 cacerts 在运行时添加证书 不要丢失来自 cacerts 的证书
怎么做:
定义自己的密钥库将证书放入密钥库使用我们的自定义类重新定义 SSL 默认上下文???利润
我的密钥库包装文件:
public class CertificateManager {
private final static Logger logger = Logger.getLogger(CertificateManager.class);
private String keyStoreLocation;
private String keyStorePassword;
private X509TrustManager myTrustManager;
private static KeyStore myTrustStore;
public CertificateManager(String keyStoreLocation, String keyStorePassword) throws Exception {
this.keyStoreLocation = keyStoreLocation;
this.keyStorePassword = keyStorePassword;
myTrustStore = createKeyStore(keyStoreLocation, keyStorePassword);
}
public void addCustomCertificate(String certFileName, String certificateAlias)
throws Exception {
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore) null);
Certificate certificate = myTrustStore.getCertificate(certificateAlias);
if (certificate == null) {
logger.info("Certificate not exists");
addCertificate(certFileName, certificateAlias);
} else {
logger.info("Certificate exists");
}
tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(myTrustStore);
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
setMytrustManager((X509TrustManager) tm);
logger.info("Trust manager found");
break;
}
}
}
private InputStream fullStream(String fname) throws IOException {
ClassLoader classLoader = getClass().getClassLoader();
InputStream resource = classLoader.getResourceAsStream(fname);
try {
if (resource != null) {
DataInputStream dis = new DataInputStream(resource);
byte[] bytes = new byte[dis.available()];
dis.readFully(bytes);
return new ByteArrayInputStream(bytes);
} else {
logger.info("resource not found");
}
} catch (Exception e) {
logger.error("exception in certificate fetching as resource", e);
}
return null;
}
public static KeyStore createKeyStore(String keystore, String pass) throws Exception {
try {
InputStream in = CertificateManager.class.getClass().getResourceAsStream(keystore);
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(in, pass.toCharArray());
logger.info("Keystore was created from resource file");
return keyStore;
} catch (Exception e) {
logger.info("Fail to create keystore from resource file");
}
File file = new File(keystore);
KeyStore keyStore = KeyStore.getInstance("JKS");
if (file.exists()) {
keyStore.load(new FileInputStream(file), pass.toCharArray());
logger.info("Default keystore loaded");
} else {
keyStore.load(null, null);
keyStore.store(new FileOutputStream(file), pass.toCharArray());
logger.info("New keystore created");
}
return keyStore;
}
private void addCertificate(String certFileName, String certificateAlias) throws CertificateException,
IOException, KeyStoreException, NoSuchAlgorithmException {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream certStream = fullStream(certFileName);
Certificate certs = cf.generateCertificate(certStream);
myTrustStore.setCertificateEntry(certificateAlias, certs);
FileOutputStream out = new FileOutputStream(getKeyStoreLocation());
myTrustStore.store(out, getKeyStorePassword().toCharArray());
out.close();
logger.info("Certificate pushed");
}
public String getKeyStoreLocation() {
return keyStoreLocation;
}
public String getKeyStorePassword() {
return keyStorePassword;
}
public X509TrustManager getMytrustManager() {
return myTrustManager;
}
public void setMytrustManager(X509TrustManager myTrustManager) {
this.myTrustManager = myTrustManager;
}
}
如有必要,此类将创建密钥库,并能够在其中管理证书。现在为 SSL 上下文类:
public class CustomTrustManager implements X509TrustManager {
private final static Logger logger = Logger.getLogger(CertificateManager.class);
private static SSLSocketFactory socketFactory;
private static CustomTrustManager instance = new CustomTrustManager();
private static List<CertificateManager> register = new ArrayList<>();
public static CustomTrustManager getInstance() {
return instance;
}
private X509TrustManager defaultTm;
public void register(CertificateManager certificateManager) {
for(CertificateManager manager : register) {
if(manager == certificateManager) {
logger.info("Certificate manager already registered");
return;
}
}
register.add(certificateManager);
logger.info("New Certificate manager registered");
}
private CustomTrustManager() {
try {
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
tmf.init((KeyStore) null);
boolean found = false;
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509TrustManager) {
defaultTm = (X509TrustManager) tm;
found = true;
break;
}
}
if(found) {
logger.info("Default trust manager found");
} else {
logger.warn("Default trust manager was not found");
}
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{this}, null);
SSLContext.setDefault(sslContext);
socketFactory = sslContext.getSocketFactory();
HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
logger.info("Custom trust manager was set");
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
logger.warn("Custom trust manager can't be set");
e.printStackTrace();
}
}
@Override
public X509Certificate[] getAcceptedIssuers() {
List<X509Certificate> out = new ArrayList<>();
if (defaultTm != null) {
out.addAll(Arrays.asList(defaultTm.getAcceptedIssuers()));
}
int defaultCount = out.size();
logger.info("Default trust manager contain " + defaultCount + " certficates");
for(CertificateManager manager : register) {
X509TrustManager customTrustManager = manager.getMytrustManager();
X509Certificate[] issuers = customTrustManager.getAcceptedIssuers();
out.addAll(Arrays.asList(issuers));
}
logger.info("Custom trust managers contain " + (out.size() - defaultCount) + " certficates");
X509Certificate[] arrayOut = new X509Certificate[out.size()];
return out.toArray(arrayOut);
}
@Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
for(CertificateManager certificateManager : register) {
X509TrustManager customTrustManager = certificateManager.getMytrustManager();
try {
customTrustManager.checkServerTrusted(chain, authType);
logger.info("Certificate chain (server) was aproved by custom trust manager");
return;
} catch (Exception e) {
}
}
if (defaultTm != null) {
defaultTm.checkServerTrusted(chain, authType);
logger.info("Certificate chain (server) was aproved by default trust manager");
} else {
logger.info("Certificate chain (server) was rejected");
throw new CertificateException("Can't check server trusted certificate.");
}
}
@Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
try {
if (defaultTm != null) {
defaultTm.checkClientTrusted(chain, authType);
logger.info("Certificate chain (client) was aproved by default trust manager");
} else {
throw new NullPointerException();
}
} catch (Exception e) {
for(CertificateManager certificateManager : register) {
X509TrustManager customTrustManager = certificateManager.getMytrustManager();
try {
customTrustManager.checkClientTrusted(chain, authType);
logger.info("Certificate chain (client) was aproved by custom trust manager");
return;
} catch (Exception e1) {
}
}
logger.info("Certificate chain (client) was rejected");
throw new CertificateException("Can't check client trusted certificate.");
}
}
public SSLSocketFactory getSocketFactory() {
return socketFactory;
}
}
这个类作为单例,因为只允许一个 defaultSSL 上下文。所以,现在用法:
CertificateManager certificateManager = new CertificateManager("C:\\myapplication\\mykeystore.jks", "changeit");
String certificatePath = "C:\\myapplication\\public_key_for_your_ssl_service.crt";
try {
certificateManager.addCustomCertificate(certificatePath, "alias_for_public_key_for_your_ssl_service");
} catch (Exception e) {
log.error("Can't add custom certificate");
e.printStackTrace();
}
CustomTrustManager.getInstance().register(certificateManager);
可能,它不适用于此设置,因为我将证书文件保存在资源文件夹中,所以我的路径不是绝对的。但总的来说,它工作得很好。
available()
的双重滥用在其自己的 Javadoc 中被特别警告。
如果您的存储库 URL 也适用于 HTTP,并且安全性不是问题,您可以转到 settings.xml(通常但不总是位于 %USERPROFILE%/.m2
)并将 HTTPS 替换为<repository>
和 <pluginRepository>
URL 的 HTTP。
例如,这个:
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>libs-release</name>
<url>https://<artifactory>/libs-release</url>
</repository>
应该替换为:
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>libs-release</name>
<url>https://<artifactory>/libs-release</url>
</repository>
我通过传递 arg -Djavax.net.ssl.trustStore=
使用自己的信任库而不是 JRE
无论信任库中的证书如何,我都会收到此错误。对我来说,问题是在 arg 行上传递的属性的顺序。当我把 -Djavax.net.ssl.trustStore=
& -Djavax.net.ssl.trustStorePassword=
之前 -Dspring.config.location=
& -jar
args 我能够通过 https 成功调用我的休息呼叫。
-"Djavax.net.ssl.trustStore"=<path>
是我所需要的。谢谢。
如果您的主机位于 firewall/proxy 后面,请在 cmd 中使用以下命令:
keytool -J-Dhttps.proxyHost=<proxy_hostname> -J-Dhttps.proxyPort=<proxy_port> -printcert -rfc -sslserver <remote_host_name:remote_ssl_port>
将 <proxy_hostname>
和 <proxy_port>
替换为配置的 HTTP 代理服务器。将 <remote_host_name:remote_ssl_port>
替换为存在认证问题的远程主机(基本上是 url)和端口之一。
取最后打印的证书内容并复制(同时复制开始和结束证书)。将其粘贴到文本文件中并为其提供 .crt 扩展名。现在使用 java keytool 命令将此证书导入 cacerts,它应该可以工作。
keytool -importcert -file <filename>.crt -alias randomaliasname -keystore %JAVA_HOME%/jre/lib/security/cacerts -storepass changeit
我遇到了同样的问题,但在我的 linux 机器上更新了错误的 jre。很有可能tomcat使用了不同的jre,并且您的cli提示配置为使用不同的jre。
确保您选择了正确的 jre。
步骤1:
ps -ef | grep tomcat
你会看到一些类似的东西:
root 29855 1 3 17:54 pts/3 00:00:42 /usr/java/jdk1.7.0_79/jre/bin/java
现在使用这个:
keytool -import -alias example -keystore /usr/java/jdk1.7.0_79/jre/lib/security/cacerts -file cert.cer
PWD: changeit
*.cer 文件可以生成如下图:(或者你可以使用你自己的)
openssl x509 -in cert.pem -outform pem -outform der -out cert.cer
如果您仍然收到此错误
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid
certification path to requested target
执行以下命令后
keytool -import -alias certificatealias -keystore C:\Program Files\Java\jre1.8.0_151\lib\security\cacerts -file certificate.cer
然后JDK中存在一些问题。尝试从受信任的提供商处安装 JDK。从受信任的提供商处重新安装后,您将不会遇到此问题。
1-首先,将您的crt文件导入{JAVA_HOME}/jre/security/cacerts,如果您仍然遇到此异常,请更改您的jdk版本。例如从 jdk1.8.0_17
到 jdk1.8.0_231
通常,当受信任证书的 PATH 不匹配时,会发生这种异常。检查安全通信需要此服务器证书的配置或路径。
它是对答案 https://stackoverflow.com/a/36427118/1491414 的补充。谢谢@MagGGG
请确保您有管理员权限
请使用双引号作为密钥库路径 (-keystore C:\Program Files (x86)\Java\jre1.6.0_22\lib\security\cacerts"),因为在 Windows 操作系统中,默认安装位置是 Program Files,您将获得由于程序文件之间的空间而导致的错误。
我使用以下方法解决了这个问题-
复制有连接问题的 url 转到 Android Studio->Settings->Http 设置 在“测试连接”中,粘贴该 url 并按 ok 点击 Ok 点击,Android Studio 将要求导入该 url 的证书,导入它就是这样。没有其他事情要做,我的问题就消失了。也无需重新启动工作室。
不定期副业成功案例分享
alias
名称应该是唯一的。