使用HttpClient通过HTTPS信任所有证书

har*_*lee 386 java ssl https certificate apache-httpclient-4.x

最近发布了一个关于HttpClient过度Https 的问题(在这里找到).我已经取得了一些进展,但我遇到了新的问题.和我的上一个问题一样,我似乎无法找到适合我的任何地方的例子.基本上,我希望我的客户端接受任何证书(因为我只指向一个服务器),但我一直在接受javax.net.ssl.SSLException: Not trusted server certificate exception.

所以这就是我所拥有的:


    public void connect() throws A_WHOLE_BUNCH_OF_EXCEPTIONS {

        HttpPost post = new HttpPost(new URI(PROD_URL));
        post.setEntity(new StringEntity(BODY));

        KeyStore trusted = KeyStore.getInstance("BKS");
        trusted.load(null, "".toCharArray());
        SSLSocketFactory sslf = new SSLSocketFactory(trusted);
        sslf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme ("https", sslf, 443));
        SingleClientConnManager cm = new SingleClientConnManager(post.getParams(),
                schemeRegistry);

        HttpClient client = new DefaultHttpClient(cm, post.getParams());
        HttpResponse result = client.execute(post);
    }
Run Code Online (Sandbox Code Playgroud)

这是我得到的错误:

    W/System.err(  901): javax.net.ssl.SSLException: Not trusted server certificate 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:360) 
    W/System.err(  901):    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:92) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:321) 
    W/System.err(  901):    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:129) 
    W/System.err(  901):    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 
    W/System.err(  901):    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 
    W/System.err(  901):    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 
    W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:129) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.access$0(MainActivity.java:77) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity$2.run(MainActivity.java:49) 
    W/System.err(  901): Caused by: java.security.cert.CertificateException: java.security.InvalidAlgorithmParameterException: the trust anchors set is empty 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:157) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:355) 
    W/System.err(  901):    ... 12 more 
    W/System.err(  901): Caused by: java.security.InvalidAlgorithmParameterException: the trust anchors set is empty 
    W/System.err(  901):    at java.security.cert.PKIXParameters.checkTrustAnchors(PKIXParameters.java:645) 
    W/System.err(  901):    at java.security.cert.PKIXParameters.<init>(PKIXParameters.java:89) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.<init>(TrustManagerImpl.java:89) 
    W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl.engineGetTrustManagers(TrustManagerFactoryImpl.java:134) 
    W/System.err(  901):    at javax.net.ssl.TrustManagerFactory.getTrustManagers(TrustManagerFactory.java:226)W/System.err(  901):     at org.apache.http.conn.ssl.SSLSocketFactory.createTrustManagers(SSLSocketFactory.java:263) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.<init>(SSLSocketFactory.java:190) 
    W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.<init>(SSLSocketFactory.java:216) 
    W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:107) 
    W/System.err(  901):    ... 2 more
Run Code Online (Sandbox Code Playgroud)

emm*_*mby 484

您基本上有四种可能的解决方案来使用httpclient修复Android上的"不受信任"异常:

  1. 信任所有证书.不要这样做,除非你真的知道你在做什么.
  2. 创建仅信任您的证书的自定义SSLSocketFactory.只要您确切知道要连接到哪些服务器,这就行,但只要您需要连接到具有不同SSL证书的新服务器,您就需要更新您的应用程序.
  3. 创建一个包含Android的证书"主列表"的密钥库文件,然后添加自己的.如果这些证书中的任何一个到期,您有责任在您的应​​用程序中更新它们.我想不出这样做的理由.
  4. 创建一个使用内置证书KeyStore的自定义SSLSocketFactory,但是对于无法使用默认值验证的任何内容,可以使用备用KeyStore.

这个答案使用的解决方案#4,在我看来是最强大的.

解决方案是使用可以接受多个KeyStore的SSLSocketFactory,允许您使用自己的证书提供自己的KeyStore.这允许您加载其他顶级证书,例如某些Android设备上可能缺少的Thawte.它还允许您加载自己的自签名证书.它将首先使用内置的默认设备证书,并仅在必要时使用其他证书.

首先,您需要确定KeyStore中缺少哪个证书.运行以下命令:

openssl s_client -connect www.yourserver.com:443
Run Code Online (Sandbox Code Playgroud)

你会看到如下输出:

Certificate chain
 0 s:/O=www.yourserver.com/OU=Go to 
   https://www.thawte.com/repository/index.html/OU=Thawte SSL123 
   certificate/OU=Domain Validated/CN=www.yourserver.com
   i:/C=US/O=Thawte, Inc./OU=Domain Validated SSL/CN=Thawte DV SSL CA
 1 s:/C=US/O=Thawte, Inc./OU=Domain Validated SSL/CN=Thawte DV SSL CA
   i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 
   2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
Run Code Online (Sandbox Code Playgroud)

如您所见,我们的根证书来自Thawte.转到您的提供商的网站,找到相应的证书.对我们来说,就在这里,您可以看到我们需要的是版权所有2006.

如果您使用的是自签名证书,则由于您已拥有签名证书,因此无需执行上一步.

然后,创建包含缺少的签名证书的密钥库文件.Crazybob 详细介绍了如何在Android上执行此操作,但其目的是执行以下操作:

如果您还没有,请从http://www.bouncycastle.org/latest_releases.html下载充气城堡提供程序库.这将在下面的类路径中进行.

运行命令以从服务器提取证书并创建pem文件.在这种情况下,mycert.pem.

echo | openssl s_client -connect ${MY_SERVER}:443 2>&1 | \
 sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > mycert.pem
Run Code Online (Sandbox Code Playgroud)

然后运行以下命令以创建密钥库.

export CLASSPATH=/path/to/bouncycastle/bcprov-jdk15on-155.jar
CERTSTORE=res/raw/mystore.bks
if [ -a $CERTSTORE ]; then
    rm $CERTSTORE || exit 1
fi
keytool \
      -import \
      -v \
      -trustcacerts \
      -alias 0 \
      -file <(openssl x509 -in mycert.pem) \
      -keystore $CERTSTORE \
      -storetype BKS \
      -provider org.bouncycastle.jce.provider.BouncyCastleProvider \
      -providerpath /path/to/bouncycastle/bcprov-jdk15on-155.jar \
      -storepass some-password
Run Code Online (Sandbox Code Playgroud)

您会注意到上面的脚本将结果放入res/raw/mystore.bks.现在您有一个文件,您将加载到您的Android应用程序中,提供缺少的证书.

为此,请为SSL方案注册SSLSocketFactory:

final SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", createAdditionalCertsSSLSocketFactory(), 443));

// and then however you create your connection manager, I use ThreadSafeClientConnManager
final HttpParams params = new BasicHttpParams();
...
final ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params,schemeRegistry);
Run Code Online (Sandbox Code Playgroud)

要创建SSLSocketFactory:

protected org.apache.http.conn.ssl.SSLSocketFactory createAdditionalCertsSSLSocketFactory() {
    try {
        final KeyStore ks = KeyStore.getInstance("BKS");

        // the bks file we generated above
        final InputStream in = context.getResources().openRawResource( R.raw.mystore);  
        try {
            // don't forget to put the password used above in strings.xml/mystore_password
            ks.load(in, context.getString( R.string.mystore_password ).toCharArray());
        } finally {
            in.close();
        }

        return new AdditionalKeyStoresSSLSocketFactory(ks);

    } catch( Exception e ) {
        throw new RuntimeException(e);
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,AdditionalKeyStoresSSLSocketFactory代码接受您的新KeyStore并检查内置KeyStore是否无法验证SSL证书:

/**
 * Allows you to trust certificates from additional KeyStores in addition to
 * the default KeyStore
 */
public class AdditionalKeyStoresSSLSocketFactory extends SSLSocketFactory {
    protected SSLContext sslContext = SSLContext.getInstance("TLS");

    public AdditionalKeyStoresSSLSocketFactory(KeyStore keyStore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(null, null, null, null, null, null);
        sslContext.init(null, new TrustManager[]{new AdditionalKeyStoresTrustManager(keyStore)}, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }



    /**
     * Based on http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#X509TrustManager
     */
    public static class AdditionalKeyStoresTrustManager implements X509TrustManager {

        protected ArrayList<X509TrustManager> x509TrustManagers = new ArrayList<X509TrustManager>();


        protected AdditionalKeyStoresTrustManager(KeyStore... additionalkeyStores) {
            final ArrayList<TrustManagerFactory> factories = new ArrayList<TrustManagerFactory>();

            try {
                // The default Trustmanager with default keystore
                final TrustManagerFactory original = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                original.init((KeyStore) null);
                factories.add(original);

                for( KeyStore keyStore : additionalkeyStores ) {
                    final TrustManagerFactory additionalCerts = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                    additionalCerts.init(keyStore);
                    factories.add(additionalCerts);
                }

            } catch (Exception e) {
                throw new RuntimeException(e);
            }



            /*
             * Iterate over the returned trustmanagers, and hold on
             * to any that are X509TrustManagers
             */
            for (TrustManagerFactory tmf : factories)
                for( TrustManager tm : tmf.getTrustManagers() )
                    if (tm instanceof X509TrustManager)
                        x509TrustManagers.add( (X509TrustManager)tm );


            if( x509TrustManagers.size()==0 )
                throw new RuntimeException("Couldn't find any X509TrustManagers");

        }

        /*
         * Delegate to the default trust manager.
         */
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            final X509TrustManager defaultX509TrustManager = x509TrustManagers.get(0);
            defaultX509TrustManager.checkClientTrusted(chain, authType);
        }

        /*
         * Loop over the trustmanagers until we find one that accepts our server
         */
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            for( X509TrustManager tm : x509TrustManagers ) {
                try {
                    tm.checkServerTrusted(chain,authType);
                    return;
                } catch( CertificateException e ) {
                    // ignore
                }
            }
            throw new CertificateException();
        }

        public X509Certificate[] getAcceptedIssuers() {
            final ArrayList<X509Certificate> list = new ArrayList<X509Certificate>();
            for( X509TrustManager tm : x509TrustManagers )
                list.addAll(Arrays.asList(tm.getAcceptedIssuers()));
            return list.toArray(new X509Certificate[list.size()]);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 这应该被标记为正确的答案.这是我见过的最彻底,写得最好的答案之一.涂料 (7认同)
  • @emmby,你能告诉我应该把这个代码出口CLASSPATH = bcprov-jdk16-145.jar的CertStore = RES /生/ mystore.bks如果[-a $的CertStore].那么rm $ CERTSTORE || 出口1音响密钥工具\ -import\-v\-trustcacerts\-alias 0\-file <(OpenSSL的X​​509 -in mycert.pem)\ -keystore $的CertStore\-storetype BKS\-provider org.bouncycastle.jce.provider. BouncyCastleProvider\-providerpath /usr/share/java/bcprov.jar\-storepass some-password (3认同)
  • 嘿@emmby。我在我的应用程序中使用您的解决方案并使用我的服务器的自签名证书,但在 **checkServerTrusted()** 方法中收到 **CertificateException()** 。我尝试评论抛出异常,并且它有效。如果它不能验证我的服务器证书,那么我可以用其他方式处理它,您能指导一下这种情况下最好的解决方案是什么吗? (2认同)

小智 414

注意:请勿在您不会完全信任的网络上使用的生产代码中实现此功能.特别是在公共互联网上的任何事情.

你的问题正是我想知道的.在我做了一些搜索后,结论如下.

在HttpClient方式中,您应该从org.apache.http.conn.ssl.SSLSocketFactory创建一个自定义类,而不是一个org.apache.http.conn.ssl.SSLSocketFactory本身.在这篇文章中可以找到一些线索.自定义SSL处理在Android 2.2 FroYo上停止工作.

一个例子是......

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

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

import org.apache.http.conn.ssl.SSLSocketFactory;
public class MySSLSocketFactory extends SSLSocketFactory {
    SSLContext sslContext = SSLContext.getInstance("TLS");

    public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(truststore);

        TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        sslContext.init(null, new TrustManager[] { tm }, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }
}
Run Code Online (Sandbox Code Playgroud)

并在创建HttpClient实例时使用此类.

public HttpClient getNewHttpClient() {
    try {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null, null);

        MySSLSocketFactory sf = new MySSLSocketFactory(trustStore);
        sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", sf, 443));

        ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

        return new DefaultHttpClient(ccm, params);
    } catch (Exception e) {
        return new DefaultHttpClient();
    }
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,下面的链接适用于正在寻找HttpURLConnection解决方案的人. Https Connection Android

我已经在froyo上测试了上述两种解决方案,在我的案例中它们都像魅力一样.最后,使用HttpURLConnection可能会面临重定向问题,但这超出了主题范围.

注意:在您决定信任所有证书之前,您可能应该完全了解该网站,并且不会对最终用户造成损害.

事实上,你应该仔细考虑你所承担的风险,包括我非常赞赏的以下评论中提到的黑客模拟网站的影响.在某些情况下,虽然可能很难处理所有证书,但您最好知道信任所有证书的隐含缺点.

  • 这个答案应该注意到,相信所有证书是非常不安全的,并使ssl的整个目的无效...... (150认同)
  • +1因为我只需要一个快速解决方案用于调试目的.由于其他人提到的安全问题,我不会在生产中使用它,但这正是我测试所需要的.谢谢! (56认同)
  • -1因为接受所有证书是一个可怕的想法.太糟糕了,有这么多的博客和教程很乐意引导Java开发人员走错路. (25认同)
  • @sweeney - 除非您无法保证与您认为自己的服务器通话.如果有人弄乱了DNS服务器,您可能正在与黑客的服务器通信加密密钥. (22认同)
  • @sweeney换句话说,你现在可能会受到中间人攻击.您还应注意该代码不符合规范:检查Javadoc.`getAcceptedIssuers()`不允许返回null. (12认同)
  • 有人能指点我一个教程,我可以接受1个可信证书而不使用一些CLI吗? (5认同)
  • 在编写代码时只有零点和一些非常真实且极大的风险,这些风险仅用于"测试".我有一个令人讨厌的怀疑,实际上确实很多,这些实现很多都会进入生产阶段,结果产生了根本不安全的系统.如果您不首先将这些安全陷门编码到您的系统中,那么这是不可能的. (5认同)
  • 那它仍然加密吧?它可能来自任何人或被任何人截获...... (2认同)
  • +1 表示实际回答问题 -1,因为客户端示例中的大多数类均已弃用 (2认同)

Alo*_*pta 71

在此之前添加此代码HttpsURLConnection,它将完成.我知道了.

private void trustEveryone() { 
    try { 
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){ 
                    public boolean verify(String hostname, SSLSession session) { 
                            return true; 
                    }}); 
            SSLContext context = SSLContext.getInstance("TLS"); 
            context.init(null, new X509TrustManager[]{new 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[0]; 
                    }}}, new SecureRandom()); 
            HttpsURLConnection.setDefaultSSLSocketFactory( 
                            context.getSocketFactory()); 
    } catch (Exception e) { // should never happen 
            e.printStackTrace(); 
    } 
} 
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助你.

  • 请参阅上面接受的答案下的评论.这种"解决方案"根本不安全. (21认同)
  • 这是理想的Q&D解决方案.简短而"正常". (5认同)
  • 完美的测试目的!是的,在生产中使用它是一个坏主意,但是继续......对于每个看问题标题的人都应该清楚.它仍然以最佳/最短/具有相同(in)安全级别来回答它! (5认同)

Dan*_*Dan 34

这是一个坏主意.信任任何证书只会(非常)比完全不使用SSL更好.当你说"我希望我的客户端接受任何证书(因为我只指向一台服务器)"时,你假设这意味着以某种方式指向"一台服务器"是安全的,而不是在公共网络上.

通过信任任何证书,您完全可以接受中间人攻击.任何人都可以通过与您和终端服务器建立单独的SSL连接来代理您的连接.然后,MITM可以访问您的整个请求和响应.除非您首先不需要SSL(您的消息没有任何敏感信息,并且不进行身份验证),否则您不应盲目信任所有证书.

您应该考虑使用keytool将公共证书添加到jks,并使用它来构建套接字工厂,例如:

    KeyStore ks = KeyStore.getInstance("JKS");

    // get user password and file input stream
    char[] password = ("mykspassword")).toCharArray();
    ClassLoader cl = this.getClass().getClassLoader();
    InputStream stream = cl.getResourceAsStream("myjks.jks");
    ks.load(stream, password);
    stream.close();

    SSLContext sc = SSLContext.getInstance("TLS");
    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
    TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");

    kmf.init(ks, password);
    tmf.init(ks);

    sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),null);

    return sc.getSocketFactory();
Run Code Online (Sandbox Code Playgroud)

这有一点需要注意.证书最终将过期,代码将在此时停止工作.您可以通过查看证书轻松确定何时发生这种情况.

  • 如果您没有使用客户端证书身份验证,则从客户端,您不需要密钥管理器(在`SSLContext.init中使用`null`).您还应该使用默认算法(KMF/TMF.getDefaultAlgorithm()),而不是硬编码`SunX509`(更多是因为TMF的默认值实际上是Sun/Oracle JVM上的`PKIX`). (5认同)

hfm*_*son 19

从API 8开始,您可以通过这种方式禁用HttpURLConnection SSL检查以进行测试:

    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    if (conn instanceof HttpsURLConnection) {
        HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
        httpsConn.setSSLSocketFactory(SSLCertificateSocketFactory.getInsecure(0, null));
        httpsConn.setHostnameVerifier(new AllowAllHostnameVerifier());
    }
Run Code Online (Sandbox Code Playgroud)

  • 不建议使用org.apache.http.conn.ssl.AllowAllHostnameVerifier。 (2认同)
  • @zackygaurav根据[javadoc](https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/conn/ssl/AllowAllHostnameVerifier.html),“ AllowAllHostnameVerifier”被替换为“ NoopH​​ostnameVerifier”。 (2认同)

小智 10

HttpComponents的API已经改变.它适用于以下代码.

public static HttpClient getTestHttpClient() {
    try {
        SSLSocketFactory sf = new SSLSocketFactory(new TrustStrategy(){
            @Override
            public boolean isTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
                return true;
            }
        }, new AllowAllHostnameVerifier());

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("https",8444, sf));
        ClientConnectionManager ccm = new ThreadSafeClientConnManager(registry);
        return new DefaultHttpClient(ccm);
    } catch (Exception e) {
        e.printStackTrace();
        return new DefaultHttpClient();
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 10

/sf/answers/446521071/上面的代码是正确的,除了它还必须调用主机名验证器:

    @Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
    SSLSocket sslSocket = (SSLSocket)sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    getHostnameVerifier().verify(host, sslSocket);
    return sslSocket;
}
Run Code Online (Sandbox Code Playgroud)

我明确注册stackoverflow以添加此修复程序.注意我的警告!


kol*_*aTM 6

信任所有证书对我来说并不是真正的替代方案,因此我执行以下操作以使 HttpsURLConnection 信任新证书(另请参阅http://nelenkov.blogspot.jp/2011/12/using-custom-certificate-trust-store- .html)。

  1. 拿到证书;我通过在 Firefox 中导出证书(单击小锁图标,获取证书详细信息,单击导出)来完成此操作,然后使用portecle导出信任库 (BKS)。

  2. 使用以下代码从 /res/raw/geotrust_cert.bks 加载 Truststore:

        final KeyStore trustStore = KeyStore.getInstance("BKS");
        final InputStream in = context.getResources().openRawResource(
                R.raw.geotrust_cert);
        trustStore.load(in, null);
    
        final TrustManagerFactory tmf = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);
    
        final SSLContext sslCtx = SSLContext.getInstance("TLS");
        sslCtx.init(null, tmf.getTrustManagers(),
                new java.security.SecureRandom());
    
        HttpsURLConnection.setDefaultSSLSocketFactory(sslCtx
                .getSocketFactory());
    
    Run Code Online (Sandbox Code Playgroud)


rai*_*tin 6

我正在为那些使用httpclient-4.5的人添加一个响应,也可能适用于4.4.

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.fluent.ContentResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;



public class HttpClientUtils{

public static HttpClient getHttpClientWithoutSslValidation_UsingHttpClient_4_5_2() {
    try {
        SSLContextBuilder builder = new SSLContextBuilder();
        builder.loadTrustMaterial(null, new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        });
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(), new NoopHostnameVerifier());
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); 
        return httpclient;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

566607 次

最近记录:

5 年,11 月 前