我试图使用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

当前回答

我留下一些小费。

使用- dsll .debug=true检查SSL。 检查您是否正在创建隧道或试图忽略它

SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (x509CertChain, authType) -> true).build();
            httpClient = HttpClientBuilder.create()
                    .setSSLContext(sslContext)
                    .setConnectionManager(new PoolingHttpClientConnectionManager(RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("http", PlainConnectionSocketFactory.INSTANCE)
                            .register("https", new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE))
                            .build()
                    )).build();

httpClient.execute(requisicao)

其他回答

这不是twitter特有的答案,但这是在搜索此错误时出现的问题。如果您的系统在连接到一个在web浏览器中查看时似乎具有有效证书的网站时接收到此错误,这可能意味着该网站具有不完整的证书链。

简单总结一下这个问题:证书颁发机构不会使用他们的根证书对任何旧证书进行签名。相反,它们(通常)签署也设置了证书颁发机构标志的中间证书(也就是说,允许签署证书)。然后,当您从CA购买证书时,他们将使用这些中间证书之一签署您的CSR。

您的Java信任存储区很可能只有根证书,而没有中间证书。

错误配置的站点可能只返回已签名的证书。问题:该站点使用的中间证书不在您的信任存储区中。浏览器将通过下载或使用缓存的中间证书来处理这个问题;这最大限度地提高了网站的兼容性。然而,Java和像OpenSSL这样的工具不会。这会导致问题中的错误。

您可以通过使用Qualys SSL测试来验证这种怀疑。如果你在网站上搜索,上面写着

此服务器的证书链不完整。

那就证实了这一点。您还可以通过查看认证路径并查看文本Extra Download来了解这一点。

How to fix it: the server administrator needs to configure the web server to return the intermediate certificates as well. For Comodo, for example, this is where the .ca-bundle file comes in handy. For example, in an Apache configuration with mod_ssl, you'd use the SSLCertificateChainFile configuration setting. For nginx, you need to concatenate the intermediate certificates and the signed certificate and use that in the SSL cert configuration. You can find more by searching for "incomplete certificate chain" online.

我也遇到了同样的问题,我使用的是8.1.0-3,但后来我使用了9.2.1-0,这个问题在没有任何手动步骤的情况下得到了修复。自签名证书工作正常。

1. 检查证书

尝试在浏览器中加载目标URL并查看网站的证书(通常可以通过带有锁标志的图标访问)。它在浏览器地址栏的左边或右边),无论它是否过期或由于其他原因不受信任。

2. 安装最新版本的JRE和JDK

新版本通常附带一组更新后的受信任证书。

如果可能的话,卸载旧版本。这将使错误配置错误显式地出现。

3.检查您的配置:

检查JAVA_HOME环境变量指向的位置。 检查您使用哪个java版本来运行程序。在IntelliJ中检查: 文件->项目结构…—>项目设置—>项目—>项目SDK: 文件->项目结构…—>平台设置—>个sdk

4. 从新的Java版本复制整个密钥存储库

如果您使用的JDK不是最新可用的JDK,请尝试将%JAVA_HOME%/jre/lib/security/cacerts文件替换为最新安装的jre中的新文件(先做备份),正如@jeremy-goodell在他的回答中建议的那样

5. 向您的密钥存储库中添加证书

如果以上都不能解决您的问题,请使用keytool将证书保存到Java的密钥存储库:

keytool -trustcacerts -keystore "%JAVA_HOME%jre\lib\security\cacerts" -storepass changeit -importcert -alias <alias_name> -file <path_to_crt_file>

正如@MagGGG在他的回答中建议的那样,可以从浏览器中获得带有证书的文件。

注1:您可能需要对链中的每个证书重复此操作,直到站点的证书。从根根开始。

注意2:<alias_name>在存储中的键中应该是唯一的,否则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

如果您的存储库URL也可以在HTTP上工作,并且安全性不是问题,您可以访问settings.xml(通常,但不总是,位于%USERPROFILE%/.m2),并将<repository>和<pluginRepository> URL的HTTPS替换为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>

Linux

下载证书:

echo \
openssl s_client -showcerts -servername DOMAIN_NAME -connect DOMAIN_NAME:443 2>/dev/null \
awk '/-----BEGIN CERTIFICATE-----/, /-----END CERTIFICATE-----/' >> ~/FILENAME.cer

占位符:

DOMAIN_NAME -服务的域名 FILENAME -文件路径证书

导入证书到Java CA证书(Java 11):

keytool -importcert -trustcacerts -file ~/FILENAME.cer -alias ca_alias -keystore $JAVA_HOME/lib/security/cacerts

输入keystore默认密码changeit 信任此证书:输入yes。输出:

Certificate was added to keystore