Tin tưởng tất cả các chứng chỉ bằng cách sử dụng HttpClient qua HTTPS


393

Gần đây đã đăng một câu hỏi liên quan đến HttpClientHttps ( tìm thấy ở đây ). Tôi đã thực hiện một số bước tiến, nhưng tôi gặp phải vấn đề mới. Như vấn đề cuối cùng của tôi, tôi dường như không thể tìm thấy một ví dụ nào phù hợp với mình. Về cơ bản, tôi muốn khách hàng của mình chấp nhận bất kỳ chứng chỉ nào (vì tôi chỉ từng trỏ đến một máy chủ) nhưng tôi vẫn nhận đượcjavax.net.ssl.SSLException: Not trusted server certificate exception.

Vì vậy, đây là những gì tôi có:


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

Và đây là lỗi tôi nhận được:

    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

17
Tôi cần phải làm điều này để sử dụng nội bộ. Tôi thực sự hy vọng bạn không cho phép người dùng bên ngoài công ty của bạn sử dụng ứng dụng của bạn vì bạn đã mở nó cho người đàn ông trong cuộc tấn công giữa và sau đó họ sẽ dễ bị ai đó chiếm quyền điều khiển phiên của họ. Tuy nhiên, tôi cần phải làm điều này tạm thời cho một số thử nghiệm cho đến khi tôi có được chứng chỉ thực trong tay ..... hy vọng bạn đang làm điều đó vì cùng một lý do tạm thời hoặc ứng dụng chỉ được sử dụng trong nội bộ.
Dean Hiller

Tôi đã thử các giải pháp này trên 4.3 apache http client, nhưng chúng hầu hết không được dùng nữa. Đây không phải là giải pháp không dùng nữa: stackoverflow.com/a/18941950/2039471
Alexander Chzhen

Java 1.6 không có hỗ trợ SNI cũng gặp vấn đề trong các tình huống này - nếu bạn không xây dựng yêu cầu đúng cách, bạn có thể nhận được chứng chỉ không khớp với yêu cầu. Xem các vấn đề.apache.org/jira/browse/HTTPCLIENT
Bron Davies

2
Câu hỏi này được trích dẫn trong Bộ luật nguy hiểm nhất thế giới như một ví dụ về lý luận sai lầm. (tài liệu nghiên cứu: cs.utexas.edu/~shmat/shmat_ccs12.pdf )
mk_

Câu trả lời:


421

Lưu ý: Không triển khai mã này trong mã sản xuất bạn sẽ sử dụng trên mạng mà bạn không hoàn toàn tin tưởng. Đặc biệt là bất cứ điều gì đi qua internet công cộng.

Câu hỏi của bạn chỉ là những gì tôi muốn biết. Sau khi tôi thực hiện một số tìm kiếm, kết luận như sau.

Theo cách của HTTPClient, bạn nên tạo một lớp tùy chỉnh từ org.apache.http.conn.ssl.SSLSocketFactory, chứ không phải là một org.apache.http.conn.ssl.SSLSocketFactory. Một số manh mối có thể được tìm thấy trong bài đăng này Xử lý SSL tùy chỉnh đã ngừng hoạt động trên Android 2.2 FroYo .

Một ví dụ giống như ...

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

và sử dụng lớp này trong khi tạo thể hiện của 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();
    }
}

BTW, liên kết dưới đây dành cho ai đó đang tìm kiếm giải pháp kết nối httpURLC. Kết nối Https Android

Tôi đã thử nghiệm hai loại giải pháp trên trên froyo và tất cả chúng đều hoạt động như một lá bùa trong trường hợp của tôi. Cuối cùng, sử dụng httpURLConnection có thể phải đối mặt với các vấn đề chuyển hướng, nhưng điều này nằm ngoài chủ đề.

Lưu ý: Trước khi bạn quyết định tin tưởng tất cả các chứng chỉ, có lẽ bạn nên biết rõ về trang web và sẽ không gây hại cho người dùng cuối.

Thật vậy, rủi ro bạn gặp phải cần được xem xét cẩn thận, bao gồm cả ảnh hưởng của trang web giả của hacker được đề cập trong các bình luận sau đây mà tôi đánh giá cao. Trong một số trường hợp, mặc dù có thể khó chăm sóc tất cả các chứng chỉ, nhưng bạn nên biết rõ hơn về những hạn chế ngầm để tin tưởng tất cả chúng.


150
câu trả lời này có lẽ nên lưu ý rằng việc tin tưởng tất cả các chứng chỉ là không an toàn khủng khiếp và vô hiệu hóa toàn bộ mục đích của ssl ...
yanokwa

22
@sweeney - Ngoại trừ việc bạn không nói chuyện với máy chủ mà bạn nghĩ là bạn không đảm bảo. Nếu ai đó đã đánh cắp máy chủ DNS, bạn có thể giao tiếp khóa mã hóa với máy chủ của hacker.
Richard Szalay

12
@sweeney Nói cách khác, bây giờ bạn phải chịu trách nhiệm về các cuộc tấn công trung gian. Bạn cũng nên lưu ý rằng mã không đáp ứng đặc điểm kỹ thuật: kiểm tra Javadoc. getAcceptedIssuers()không được phép trả về null.
Hầu tước Lorne

25
-1 Bởi vì đó là một ý tưởng khủng khiếp để chấp nhận tất cả các chứng chỉ. Thật tệ khi có rất nhiều blog và hướng dẫn vui vẻ hướng dẫn các nhà phát triển Java trên con đường làm điều sai trái.
Tim Bender

57
+1 Bởi vì tôi cần một giải pháp nhanh chóng cho mục đích gỡ lỗi. Tôi sẽ không sử dụng điều này trong sản xuất do những lo ngại về bảo mật mà người khác đã đề cập, nhưng đây chính xác là những gì tôi cần để thử nghiệm. Cảm ơn bạn!
Danation

495

Về cơ bản, bạn có bốn giải pháp tiềm năng để khắc phục ngoại lệ "Không đáng tin cậy" trên Android bằng httpclient:

  1. Tin tưởng tất cả các chứng chỉ. Đừng làm điều này, trừ khi bạn thực sự biết những gì bạn đang làm.
  2. Tạo SSLSocketFactory tùy chỉnh chỉ tin tưởng chứng chỉ của bạn. Điều này hoạt động miễn là bạn biết chính xác máy chủ nào bạn sẽ kết nối, nhưng ngay khi bạn cần kết nối với máy chủ mới có chứng chỉ SSL khác, bạn sẽ cần cập nhật ứng dụng của mình.
  3. Tạo một tệp kho khóa chứa "danh sách chính" các chứng chỉ của Android, sau đó thêm chứng chỉ của riêng bạn. Nếu bất kỳ trong số các certs hết hạn trên đường, bạn có trách nhiệm cập nhật chúng trong ứng dụng của bạn. Tôi không thể nghĩ ra một lý do để làm điều này.
  4. Tạo SSLSocketFactory tùy chỉnh sử dụng KeyStore chứng chỉ tích hợp, nhưng lại rơi vào KeyStore thay thế cho bất kỳ điều gì không xác minh được với mặc định.

Câu trả lời này sử dụng giải pháp số 4, dường như đối với tôi là mạnh mẽ nhất.

Giải pháp là sử dụng SSLSocketFactory có thể chấp nhận nhiều KeyStor, cho phép bạn cung cấp KeyStore của riêng bạn với các chứng chỉ của riêng bạn. Điều này cho phép bạn tải thêm các chứng chỉ cấp cao nhất như Thawte có thể bị thiếu trên một số thiết bị Android. Nó cũng cho phép bạn tải các chứng chỉ tự ký của riêng bạn là tốt. Trước tiên, nó sẽ sử dụng chứng chỉ thiết bị mặc định tích hợp sẵn và chỉ quay lại chứng chỉ bổ sung của bạn khi cần thiết.

Trước tiên, bạn sẽ muốn xác định chứng chỉ nào bạn đang thiếu trong KeyStore. Chạy lệnh sau:

openssl s_client -connect www.yourserver.com:443

Và bạn sẽ thấy đầu ra như sau:

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

Như bạn có thể thấy, chứng chỉ gốc của chúng tôi là từ Thawte. Truy cập trang web của nhà cung cấp của bạn và tìm chứng chỉ tương ứng. Đối với chúng tôi, nó đã ở đây và bạn có thể thấy rằng cái chúng tôi cần là bản quyền 2006.

Nếu bạn đang sử dụng chứng chỉ tự ký, bạn không cần thực hiện bước trước vì bạn đã có chứng chỉ ký.

Sau đó, tạo một tệp kho khóa chứa chứng chỉ ký bị thiếu. Crazybob có chi tiết cách thực hiện việc này trên Android , nhưng ý tưởng là làm như sau:

Nếu bạn chưa có nó, hãy tải xuống thư viện nhà cung cấp lâu đài bouncy từ: http://www.bouncycastle.org/latest_release.html . Điều này sẽ đi trên classpath của bạn dưới đây.

Chạy một lệnh để trích xuất chứng chỉ từ máy chủ và tạo một tệp pem. Trong trường hợp này, mycert.pem.

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

Sau đó chạy các lệnh sau để tạo kho khóa.

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

Bạn sẽ nhận thấy rằng tập lệnh trên đặt kết quả vào res/raw/mystore.bks. Bây giờ bạn có một tệp bạn sẽ tải vào ứng dụng Android cung cấp (các) chứng chỉ bị thiếu.

Để thực hiện việc này, hãy đăng ký SSLSocketFactory của bạn cho chương trình SSL:

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

Để tạo SSLSocketFactory của bạn:

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

Và cuối cùng, mã ExtraKeyStoresSSLSocketFactory, chấp nhận KeyStore mới của bạn và kiểm tra xem KeyStore tích hợp không xác thực chứng chỉ 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()]);
        }
    }

}

Xin chào @emmby, đây có vẻ là câu trả lời hoàn hảo cho vấn đề của tôi, nhưng tôi vẫn không có kết nối SSL. Bạn có thể vui lòng xem nó? http://stackoverflow.com/questions/7822381/need-help-understanding-certificate-chains
Matthias B

Cảm ơn vì đã viết tuyệt vời @emmby! Đôi khi tôi nhận được một độ trễ thực sự dài và sau đó là một javax.net.ssl.SSLException: Đọc lỗi :. Bất kỳ ý tưởng? Làm cách nào tôi có thể đặt thời gian chờ nếu giải pháp giống như stackoverflow.com/questions/5909308/android-2-3-4-ssl-probols ?
Edwin Evans

3
@emmby, bạn có thể cho biết nơi tôi nên đặt mã này xuất CLASSPATH = bcprov-jdk16-145.jar CERTSTORE = res / raw / mystore.bks if [-a $ CERTSTORE]; sau đó rm $ CERTSTORE || thoát 1 fi keytool \ -import \ -v \ -trustcacerts \ -alias 0 \ -file <(openssl x509 -in mycert.pem) \ -keystore $ CERTSTORE \ -storetype BKS \ -provider org.bouncycast. BouncyCastleProvider \ -providerpath /usr/share/java/bcprov.jar \ -storepass some-password
Rikki Tikki Tavi

1
Này @emmby. Tôi đang sử dụng giải pháp của bạn trong ứng dụng của tôi và sử dụng tự ký giấy chứng nhận máy chủ của tôi nhưng nhận được một CertificateException () trong checkServerTrusted () phương pháp. Tôi đã cố gắng bình luận rằng ném ngoại lệ, và nó hoạt động. Nếu nó không xác nhận chứng chỉ máy chủ của tôi thì tôi có thể xử lý nó theo cách khác không, bạn có thể hướng dẫn giải pháp tốt nhất trong trường hợp này là gì không?
Ankit

7
Điều này nên được đánh dấu là câu trả lời đúng. Một trong những câu trả lời thấu đáo và được viết tốt nhất mà tôi từng thấy trên SO. Dope
Kachi

74

Thêm mã này trước HttpsURLConnectionvà nó sẽ được thực hiện. Tôi hiểu rồi.

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

Tôi hy vọng cái này sẽ giúp bạn.


22
Xem các nhận xét trên dưới câu trả lời được chấp nhận. "Giải pháp" này hoàn toàn không an toàn.
Hầu tước Lorne

5
Đây là giải pháp Q & D lý tưởng. Ngắn gọn và "chỉ hoạt động".
Steve Smith

5
Câu trả lời hoàn hảo cho mục đích thử nghiệm !!! Và vâng, đó là một ý tưởng tồi để sử dụng trong sản xuất, nhưng thôi nào ... điều đó rõ ràng với mọi người khi nhìn vào tiêu đề câu hỏi. Nó vẫn trả lời tốt nhất / ngắn nhất / với cùng mức bảo mật (trong)!
Levite

34

Đây là một ý tưởng tồi. Tin tưởng bất kỳ chứng chỉ nào chỉ (rất) tốt hơn một chút so với việc không sử dụng SSL. Khi bạn nói "Tôi muốn khách hàng của mình chấp nhận bất kỳ chứng chỉ nào (vì tôi chỉ bao giờ chỉ đến một máy chủ)", bạn cho rằng điều này có nghĩa là bằng cách nào đó chỉ đến "một máy chủ" là an toàn, không phải trên mạng công cộng.

Bạn hoàn toàn cởi mở với một cuộc tấn công trung gian bằng cách tin tưởng bất kỳ chứng chỉ nào. Bất cứ ai cũng có thể ủy quyền kết nối của bạn bằng cách thiết lập kết nối SSL riêng với bạn và với máy chủ cuối. MITM sau đó có quyền truy cập vào toàn bộ yêu cầu và phản hồi của bạn. Trừ khi bạn không thực sự cần SSL ở nơi đầu tiên (tin nhắn của bạn không có gì nhạy cảm và không xác thực), bạn không nên tin tưởng tất cả các chứng chỉ một cách mù quáng.

Bạn nên xem xét việc thêm chứng chỉ công khai vào jks bằng keytool và sử dụng chứng chỉ đó để xây dựng nhà máy ổ cắm của bạn, chẳng hạn như:

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

Điều này có một cảnh báo để xem ra. Chứng chỉ cuối cùng sẽ hết hạn và mã sẽ ngừng hoạt động tại thời điểm đó. Bạn có thể dễ dàng xác định khi nào điều này sẽ xảy ra bằng cách nhìn vào chứng chỉ.


5
Nếu bạn không sử dụng xác thực chứng chỉ ứng dụng khách, từ phía máy khách, bạn không cần sử dụng khóa phím ( sử dụng nulltrong SSLContext.init). You should also use the default algorithms (KMF/TMF.getDefaultAlgorithm() ), instead of hard-coding SunX509` (hơn nữa vì mặc định cho TMF thực sự PKIXnằm trên Sun / Oracle JVM).
Bruno

Tồn tại một tập tin chứng chỉ gốc? (giống như các trình duyệt làm)
dani herrera

Trường hợp đã myjks.jksđến từ đâu?
zionpi

1
@zionpi Được tạo bằng Java "keytool".
Dan

22

Bạn có thể vô hiệu hóa kiểm tra SSL HTTPURLConnection cho mục đích thử nghiệm theo cách này kể từ API 8:

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

2
org.apache.http.conn.ssl.AllowAllHostnameVerifierbị phản đối
zackygaurav

2
@zackygaurav Theo javadoc , AllowAllHostnameVerifierđược thay thế bằng NoopHostnameVerifier"
DLight

10

API của HttpComponents đã được thay đổi. Nó hoạt động với mã dưới đây.

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

Sử dụng một chiến lược tin cậy tùy chỉnh là câu trả lời đúng. Cảm ơn.
Matt Friedman

10

Mã ở trên trong https://stackoverflow.com/a/6378872/1553004 là chính xác, ngoại trừ nó PHẢI gọi trình xác minh tên máy chủ:

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

Tôi đã đăng ký stackoverflow rõ ràng để thêm sửa lỗi này. Hãy chú ý đến lời cảnh báo của tôi!


Khi bạn xác minh chứng chỉ theo cách này trên kết nối đầu tiên, bạn sẽ làm gì với các kết nối tiếp theo? Bạn có tận dụng kiến ​​thức bạn có được từ kết nối đầu tiên không? Điều gì xảy ra nếu một chứng chỉ giả có cùng tên được sử dụng trong lần thử kết nối 3?
jww

6

Tôi đang thêm một phản hồi cho những người sử dụng httpclient-4.5 và có thể cũng hoạt động cho 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);
    }
}
}

Lớp NoophostnameVerifier () mới là gì?
Mushtakim Ahmed Ansari

1
@MushtakimAhmedAnsari Từ các tài liệu: "NO_OP HostnameVerifier về cơ bản sẽ tắt xác minh tên máy chủ. Việc triển khai này là không hoạt động và không bao giờ ném SSLException."
raisercostin

Cảm ơn câu trả lời tuyệt vời. Cái này sẽ nhận được nhiều phiếu hơn.
Abhay Dwivingi

Làm thế nào để tôi sử dụng nó? hoặc bạn đang đề xuất rằng chỉ cần có lớp sẽ ghi đè xác minh chứng chỉ ssl?
xử

Đúng. rằng httpClient khi được sử dụng sẽ không xác thực chứng chỉ https
raisercostin

4

Tin tưởng tất cả các chứng chỉ không phải là sự thay thế thực sự đối với tôi, vì vậy tôi đã làm như sau để có được HttpsURLCconnectection để tin vào một chứng chỉ mới (xem thêm http://nelenkov.blogspot.jp/2011/12/USE-custom-cert ve -trust-store- trên.html ).

  1. Nhận chứng chỉ; Tôi đã thực hiện điều này bằng cách xuất chứng chỉ trong Firefox (nhấp vào biểu tượng khóa nhỏ, lấy chi tiết chứng chỉ, nhấp vào xuất), sau đó sử dụng portecle để xuất kho tin cậy (BKS).

  2. Tải Truststore từ /res/raw/geotrust_cert.bks với mã sau:

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

Tôi nhận được lỗi này. IOExceptionjavax.net.ssl.SSLPeerUnverifiedException: No peer certificate. Điều này khi thực hiện cuộc gọi thực thi thực tế trên HttpClient sau khi thiết lập ở trên được thực hiện.
Michael

3

Đây là một phiên bản đơn giản sử dụng mã httpclient 4.1.2. Điều này sau đó có thể được sửa đổi thành bất kỳ thuật toán tin cậy mà bạn thấy phù hợp.

public static HttpClient getTestHttpClient() {
    try {
        SSLSocketFactory sf = new SSLSocketFactory(new TrustStrategy(){
            @Override
            public boolean isTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
                return true;
            }
        });
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("https", 443, sf));
        ClientConnectionManager ccm = new ThreadSafeClientConnManager(registry);
        return new DefaultHttpClient(ccm);
    } catch (Exception e) {
        return new DefaultHttpClient();
    }
}

3

Tôi đã xem phản hồi từ "emmby" (đã trả lời 16 tháng 6, 11 lúc 21 giờ 29 phút), mục số 4: "Tạo SSLSocketFactory tùy chỉnh sử dụng KeyStore chứng chỉ tích hợp, nhưng lại rơi vào KeyStore thay thế cho bất kỳ lỗi nào để xác minh với mặc định. "

Đây là một thực hiện đơn giản hóa. Tải kho khóa hệ thống và hợp nhất với kho khóa ứng dụng.

public HttpClient getNewHttpClient() {
    try {
        InputStream in = null;
        // Load default system keystore
        KeyStore trusted = KeyStore.getInstance(KeyStore.getDefaultType()); 
        try {
            in = new BufferedInputStream(new FileInputStream(System.getProperty("javax.net.ssl.trustStore"))); // Normally: "/system/etc/security/cacerts.bks"
            trusted.load(in, null); // no password is "changeit"
        } finally {
            if (in != null) {
                in.close();
                in = null;
            }
        }

        // Load application keystore & merge with system
        try {
            KeyStore appTrusted = KeyStore.getInstance("BKS"); 
            in = context.getResources().openRawResource(R.raw.mykeystore);
            appTrusted.load(in, null); // no password is "changeit"
            for (Enumeration<String> e = appTrusted.aliases(); e.hasMoreElements();) {
                final String alias = e.nextElement();
                final KeyStore.Entry entry = appTrusted.getEntry(alias, null);
                trusted.setEntry(System.currentTimeMillis() + ":" + alias, entry, null);
            }
        } finally {
            if (in != null) {
                in.close();
                in = null;
            }
        }

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

        SSLSocketFactory sf = new SSLSocketFactory(trusted);
        sf.setHostnameVerifier(SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

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

Một chế độ đơn giản để chuyển đổi từ JKS sang BKS:

keytool -importkeystore -destkeystore cacerts.bks -deststoretype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-jdk16-141.jar -deststorepass changeit -srcstorepass changeit -srckeystore $JAVA_HOME/jre/lib/security/cacerts -srcstoretype JKS -noprompt

* Lưu ý: Trong Android 4.0 (ICS), Cửa hàng ủy thác đã thay đổi, thông tin thêm: http://nelenkov.blogspot.com.es/2011/12/ics-trust-store-im THỰCation.html


3

Đối với những người muốn cho phép tất cả các chứng chỉ hoạt động (cho mục đích thử nghiệm) qua OAuth, hãy làm theo các bước sau:

1) Tải xuống mã nguồn của API OAuth của Android tại đây: https://github.com/kaeppler/signpost

2) Tìm tập tin lớp "CommonsHttpOAuthProvider"

3) Thay đổi nó như sau:

public class CommonsHttpOAuthProvider extends AbstractOAuthProvider {

private static final long serialVersionUID = 1L;

private transient HttpClient httpClient;

public CommonsHttpOAuthProvider(String requestTokenEndpointUrl, String accessTokenEndpointUrl,
        String authorizationWebsiteUrl) {
    super(requestTokenEndpointUrl, accessTokenEndpointUrl, authorizationWebsiteUrl);


    //this.httpClient = new DefaultHttpClient();//Version implemented and that throws the famous "javax.net.ssl.SSLException: Not trusted server certificate" if the certificate is not signed with a CA
    this.httpClient = MySSLSocketFactory.getNewHttpClient();//This will work with all certificates (for testing purposes only)
}

"MySSLSocketFactory" ở trên dựa trên câu trả lời được chấp nhận. Để làm cho nó dễ dàng hơn nữa, ở đây đi đến lớp hoàn chỉnh:

package com.netcomps.oauth_example;

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.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;

//http://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https
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() {

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

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

        @Override
        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();
}



public static HttpClient getNewHttpClient() {

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

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

}

Hy vọng điều này sẽ giúp được ai đó.


1
Câu hỏi là HttpClientvà HTTPS; không phải OAuth cho Android từ dự án GitHub.
jww

3

Tôi đã sử dụng nó và nó hoạt động cho tôi trên tất cả các hệ điều hành.

/**
 * Disables the SSL certificate checking for new instances of {@link HttpsURLConnection} This has been created to
 * aid testing on a local box, not for use on production.
 */


private static void disableSSLCertificateChecking() {
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
            // Not implemented
        }

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
            // Not implemented
        }
    } };

    try {
        SSLContext sc = SSLContext.getInstance("TLS");

        sc.init(null, trustAllCerts, new java.security.SecureRandom());

        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}

Xin chào @ yegor256, tôi đang sử dụng mã này, nhưng vẫn gặp sự cố bắt tay SSL
user2028


0

Bất kỳ ai vẫn đang vật lộn với Chứng chỉ SSL StartCom trên Android 2.1, hãy truy cập https://www.startssl.com/certs/ và tải xuống ca.pem, bây giờ trong câu trả lời được cung cấp bởi @emmby thay thế

`export CLASSPATH=bcprov-jdk16-145.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 /usr/share/java/bcprov.jar \
  -storepass some-password`

với

 `export CLASSPATH=bcprov-jdk16-145.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 ca.pem) \
  -keystore $CERTSTORE \
  -storetype BKS \
  -provider org.bouncycastle.jce.provider.BouncyCastleProvider \
  -providerpath /usr/share/java/bcprov.jar \
  -storepass some-password`

Nên làm việc ra khỏi hộp. Tôi đã vật lộn nó trong hơn một ngày ngay cả sau khi một câu trả lời hoàn hảo của @emmby .. Hy vọng điều này sẽ giúp ai đó ...


0

sử dụng lớp học này

public class WCFs
{
    //  https://192.168.30.8/myservice.svc?wsdl
private static final String NAMESPACE = "http://tempuri.org/";
private static final String URL = "192.168.30.8";
private static final String SERVICE = "/myservice.svc?wsdl";
private static String SOAP_ACTION = "http://tempuri.org/iWCFserviceMe/";


public static Thread myMethod(Runnable rp)
{
    String METHOD_NAME = "myMethod";

    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

    request.addProperty("Message", "Https WCF Running...");
    return _call(rp,METHOD_NAME, request);
}

protected static HandlerThread _call(final RunProcess rp,final String METHOD_NAME, SoapObject soapReq)
{
    final SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    int TimeOut = 5*1000;

    envelope.dotNet = true;
    envelope.bodyOut = soapReq;
    envelope.setOutputSoapObject(soapReq);

    final HttpsTransportSE httpTransport_net = new HttpsTransportSE(URL, 443, SERVICE, TimeOut);

    try
    {
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() // use this section if crt file is handmake
        {
            @Override
            public boolean verify(String hostname, SSLSession session)
            {
                return true;
            }
        });

        KeyStore k = getFromRaw(R.raw.key, "PKCS12", "password");
        ((HttpsServiceConnectionSE) httpTransport_net.getServiceConnection()).setSSLSocketFactory(getSSLSocketFactory(k, "SSL"));


    }
    catch(Exception e){}

    HandlerThread thread = new HandlerThread("wcfTd"+ Generator.getRandomNumber())
    {
        @Override
        public void run()
        {
            Handler h = new Handler(Looper.getMainLooper());
            Object response = null;

            for(int i=0; i<4; i++)
            {
                response = send(envelope, httpTransport_net , METHOD_NAME, null);

                try
                {if(Thread.currentThread().isInterrupted()) return;}catch(Exception e){}

                if(response != null)
                    break;

                ThreadHelper.threadSleep(250);
            }

            if(response != null)
            {
                if(rp != null)
                {
                    rp.setArguments(response.toString());
                    h.post(rp);
                }
            }
            else
            {
                if(Thread.currentThread().isInterrupted())
                    return;

                if(rp != null)
                {
                    rp.setExceptionState(true);
                    h.post(rp);
                }
            }

            ThreadHelper.stopThread(this);
        }
    };

    thread.start();

    return thread;
}


private static Object send(SoapSerializationEnvelope envelope, HttpTransportSE androidHttpTransport, String METHOD_NAME, List<HeaderProperty> headerList)
{
    try
    {
        if(headerList != null)
            androidHttpTransport.call(SOAP_ACTION + METHOD_NAME, envelope, headerList);
        else
            androidHttpTransport.call(SOAP_ACTION + METHOD_NAME, envelope);

        Object res = envelope.getResponse();

        if(res instanceof SoapPrimitive)
            return (SoapPrimitive) envelope.getResponse();
        else if(res instanceof SoapObject)
            return ((SoapObject) envelope.getResponse());
    }
    catch(Exception e)
    {}

    return null;
}

public static KeyStore getFromRaw(@RawRes int id, String algorithm, String filePassword)
{
    try
    {
        InputStream inputStream = ResourceMaster.openRaw(id);
        KeyStore keystore = KeyStore.getInstance(algorithm);
        keystore.load(inputStream, filePassword.toCharArray());
        inputStream.close();

        return keystore;
    }
    catch(Exception e)
    {}

    return null;
}

public static SSLSocketFactory getSSLSocketFactory(KeyStore trustKey, String SSLAlgorithm)
{
    try
    {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustKey);

        SSLContext context = SSLContext.getInstance(SSLAlgorithm);//"SSL" "TLS"
        context.init(null, tmf.getTrustManagers(), null);

        return context.getSocketFactory();
    }
    catch(Exception e){}

    return null;
}

}


0

nhập mô tả hình ảnh ở đây

Một sspi thất bại trong xamarin android.

Tôi tìm thấy giải pháp này; đặt mã này trước khi bạn nhấn vào liên kết HTTPS

const SslProtocols _Tls12 = (SslProtocols)0x00000C00;
const SecurityProtocolType Tls12 = (SecurityProtocolType)_Tls12;
ServicePointManager.SecurityProtocol = Tls12;

-3

làm việc với tất cả 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));

2
Chỉ cần lặp lại cùng một giải pháp phi an toàn ngụy biện đã được thảo luận và loại bỏ trong chủ đề này.
Hầu tước Lorne

-3

Có rất nhiều câu trả lời ở trên nhưng tôi không thể làm cho bất kỳ câu trả lời nào hoạt động chính xác (với thời gian giới hạn của tôi), vì vậy với bất kỳ ai khác trong tình huống tương tự, bạn có thể thử mã dưới đây hoạt động hoàn hảo cho mục đích thử nghiệm java của tôi:

    public static HttpClient wrapClient(HttpClient base) {
    try {
        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);
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        ClientConnectionManager ccm = base.getConnectionManager();
        SchemeRegistry sr = ccm.getSchemeRegistry();
        sr.register(new Scheme("https", ssf, 443));
        return new DefaultHttpClient(ccm, base.getParams());
    } catch (Exception ex) {
        return null;
    }
}

và gọi như:

DefaultHttpClient baseClient = new DefaultHttpClient();
HttpClient httpClient = wrapClient(baseClient );

Tham khảo: http://tech.chitgoks.com/2011/04/24/how-to-avoid-javax-net-ssl-sslpeerunverifiedexception-peer-not-authenticated-probols-USE-apache-httpclient/


Để trích dẫn EJP: "Chỉ cần lặp lại cùng một giải pháp phi an toàn ngụy biện đã được thảo luận và loại bỏ trong chủ đề này" .
jww

-4

Đơn giản chỉ cần sử dụng cái này -

public DefaultHttpClient wrapClient(HttpClient base) {
    try {
        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);
    ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    ClientConnectionManager ccm = base.getConnectionManager();
    SchemeRegistry sr = ccm.getSchemeRegistry();
    sr.register(new Scheme("https", ssf, 443));
    return new DefaultHttpClient(ccm, base.getParams());
} catch (Exception ex) {
    return null;
}
}

Để trích dẫn EJP: "Chỉ cần lặp lại cùng một giải pháp phi an toàn ngụy biện đã được thảo luận và loại bỏ trong chủ đề này" .
jww

-5

Câu trả lời của Daniel rất tốt trừ tôi phải thay đổi mã này ...

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

mã này ...

    ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
    SchemeRegistry registry = ccm.getShemeRegistry()
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    registry.register(new Scheme("https", sf, 443));

để làm cho nó hoạt động.


5
Làm thế nào nên làm việc? bạn tham khảo sổ đăng ký trước khi bạn thậm chí tạo ra nó!
Matthias B
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.