Trusting all certificates using HttpClient over HT

2020-01-22 10:42发布

Recently posted a question regarding the HttpClient over Https (found here). I've made some headway, but I've run into new issues. As with my last problem, I can't seem to find an example anywhere that works for me. Basically, I want my client to accept any certificate (because I'm only ever pointing to one server) but I keep getting a javax.net.ssl.SSLException: Not trusted server certificate exception.

So this is what I have:


    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);
    }

And here's the error I'm getting:

    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

21条回答
放我归山
2楼-- · 2020-01-22 11:45

enter image description here

A sspi failed in xamarin android.

I found this solution; put this code before you hit on an HTTPS link

const SslProtocols _Tls12 = (SslProtocols)0x00000C00;
const SecurityProtocolType Tls12 = (SecurityProtocolType)_Tls12;
ServicePointManager.SecurityProtocol = Tls12;
查看更多
何必那么认真
3楼-- · 2020-01-22 11:45

work with all https

httpClient = new DefaultHttpClient();

SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
    public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

    public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }

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

ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 443, ssf));
查看更多
该账号已被封号
4楼-- · 2020-01-22 11:48

This is a bad idea. Trusting any certificate is only (very) slightly better than using no SSL at all. When you say "I want my client to accept any certificate (because I'm only ever pointing to one server)" you are assuming this means that somehow pointing to "one server" is safe, which it's not on a public network.

You are completely open to a man-in-the-middle attack by trusting any certificate. Anyone can proxy your connection by establishing a separate SSL connection with you and with the end server. The MITM then has access to your entire request and response. Unless you didn't really need SSL in the first place (your message has nothing sensitive, and doesn't do authentication) you shouldn't trust all certificates blindly.

You should consider adding the public cert to a jks using keytool, and using that to build your socket factory, such as this:

    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();

This has one caveat to watch out for. The certificate will expire eventually, and the code will stop working at that time. You can easily determine when this will happen by looking at the cert.

查看更多
登录 后发表回答