当前位置:  开发笔记 > 编程语言 > 正文

使用HTTPS的HttpGet:SSLPeerUnverifiedException

如何解决《使用HTTPS的HttpGet:SSLPeerUnverifiedException》经验,为你挑选了3个好方法。

使用HttpClient时,尝试通过HTTPS进行通信时收到以下错误:

线程"main"中的异常javax.net.ssl.SSLPeerUnverifiedException:peer未经过身份验证.

这是我的代码:

URI loginUri = new URI("https://myUrl.asp");

HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet( loginUri );
HttpResponse response = httpclient.execute( httpget );

如何抑制或删除此错误?



1> Jonas Anders..:

注意:请勿在生产代码中执行此操作,而是使用http代替,或者按照上面的建议使用实际的自签名公钥.

在HttpClient 4.xx上:

import static org.junit.Assert.assertEquals;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.junit.Test;

public class HttpClientTrustingAllCertsTest {

    @Test
    public void shouldAcceptUnsafeCerts() throws Exception {
        DefaultHttpClient httpclient = httpClientTrustingAllSSLCerts();
        HttpGet httpGet = new HttpGet("https://host_with_self_signed_cert");
        HttpResponse response = httpclient.execute( httpGet );
        assertEquals("HTTP/1.1 200 OK", response.getStatusLine().toString());
    }

    private DefaultHttpClient httpClientTrustingAllSSLCerts() throws NoSuchAlgorithmException, KeyManagementException {
        DefaultHttpClient httpclient = new DefaultHttpClient();

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, getTrustingManager(), new java.security.SecureRandom());

        SSLSocketFactory socketFactory = new SSLSocketFactory(sc);
        Scheme sch = new Scheme("https", 443, socketFactory);
        httpclient.getConnectionManager().getSchemeRegistry().register(sch);
        return httpclient;
    }

    private TrustManager[] getTrustingManager() {
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            @Override
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
                // Do nothing
            }

            @Override
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
                // Do nothing
            }

        } };
        return trustAllCerts;
    }
}


而且,对于任何对安全感兴趣的人来说,这并不能解决潜在的问题.在证书存储区中导入证书,但不要信任所有连接,因为您可能不使用SSL.
当然.在生产代码中执行上述操作将极其适得其反.但是,如果您不关心安全性,例如在针对开发服务器的端到端测试中,那么不依赖于服务器证书是件好事.
我假设您使用加密的目的是阻止中间人阅读您的数据.如果是这样,在没有验证证书的情况下,你不知道谁在另一端,它可能是代理通信的中间人,即解密它,读取它,加密它,传递它.你永远不会知道...

2> Barett..:

这个答案是关于owlstead和Mat的回答.它适用于SE/EE安装,而不适用于ME /移动/ Android SSL.

由于还没有人提到它,我将提到修复此问题的"生产方式":按照HttpClient中的AuthSSLProtocolSocketFactory类中的步骤更新您的信任库和密钥库.

    导入受信任的证书并生成信任库文件

keytool -import -alias "my server cert" -file server.crt -keystore my.truststore

    生成新密钥(使用与信任库相同的密码)

keytool -genkey -v -alias "my client key" -validity 365 -keystore my.keystore

    发出证书签名请求(CSR)

keytool -certreq -alias "my client key" -file mycertreq.csr -keystore my.keystore

    (自签或签署证书)

    导入受信任的CA根证书

keytool -import -alias "my trusted ca" -file caroot.crt -keystore my.keystore

    导入包含完整证书链的PKCS#7文件

keytool -import -alias "my client key" -file mycert.p7 -keystore my.keystore

    验证生成的密钥库文件的内容

keytool -list -v -keystore my.keystore

如果您没有服务器证书,请以JKS格式生成一个,然后将其导出为CRT文件.来源:keytool文档

keytool -genkey -alias server-alias -keyalg RSA -keypass changeit
    -storepass changeit -keystore my.keystore

keytool -export -alias server-alias -storepass changeit
    -file server.crt -keystore my.keystore



3> Stefan Kenda..:

使用HttpClient 3.x,您需要这样做:

Protocol easyHttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
Protocol.registerProtocol("https", easyHttps);

可以在此处找到EasySSLProtocolSocketFactory的实现.


应该注意的是,此方法完全符合问题的要求:它会抑制错误消息.它实际上并没有解决问题,因为连接是不安全的.正确的方法是在您的信任库中明确导入远程证书.
推荐阅读
ERIK又
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有