it-swarm-ko.tech

HttpClient를 모든 인증서 신뢰를 사용하는 HTTPS

최근 Https ( 여기에서 )에서 HttpClient에 관한 질문을 게시했습니다. 나는 약간의 진전을 이루었지만 새로운 문제에 봉착했습니다. 나의 마지막 문제와 마찬가지로, 나는 나를 위해 일하는 곳 어디에서도 예를 찾을 수없는 것 같다. 기본적으로, 나는 내 클라이언트가 모든 인증서를 받아들이기를 원한다. 왜냐하면 나는 오직 하나의 서버를 가리키고 있기 때문이다. 그러나 나는 계속 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);
    }

그리고 여기에 내가 얻는 오류가있다.

    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
377
harrisonlee

참고 : 전적으로 신뢰하지 않는 네트워크에서 사용하려고하는 프로덕션 코드에서는이를 구현하지 마십시오. 특히 공중 인터넷을 통해 진행되는 모든 것.

당신의 질문은 제가 알고 싶은 것입니다. 몇 가지 검색을 한 후에 결론은 다음과 같습니다.

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

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, 아래의 링크는 HttpURLConnection 솔루션을 찾고있는 사람을위한 것입니다. Https 연결 Android

내가 위의 두 가지 솔루션을 froyo에서 테스트했으며, 모두 내 경우에 매력처럼 작동합니다. 마지막으로 HttpURLConnection을 사용하면 리디렉션 문제가 발생할 수 있지만 주제를 벗어난다.

참고 : 모든 인증서를 신뢰하기로 결정하기 전에 사이트를 잘 알고 있어야하며 최종 사용자에게 유해하지 않습니다.

실제로, 귀하가 취하는 위험은 신중하게 고려해야합니다. 해커의 모의 사이트의 영향을 포함하여 다음과 같은 의견에 진심으로 감사드립니다. 어떤 상황에서는 모든 인증서를 처리하는 것이 어려울지라도 모든 인증서를 신뢰하는 암시 적 단점을 더 잘 알아야합니다.

411
Daniel

기본적으로 당신은 안드로이드에서 httpclient를 사용하여 "Not Trusted"예외를 수정하기위한 네 가지 잠재적 인 해결책을 가지고 있습니다 :

  1. 모든 인증서를 신뢰하십시오. 당신이하는 일을 정말로 알지 못한다면, 이것을하지 마십시오.
  2. 자신의 증명서만을 신뢰하는 커스텀 SSLSocketFactory를 작성합니다. 이는 연결하려는 서버를 정확히 알고있는 한 계속 작동하지만 다른 SSL 인증서로 새 서버에 연결해야하는 즉시 앱을 업데이트해야합니다.
  3. Android의 "마스터 목록"인증서가 포함 된 키 저장소 파일을 만든 다음 자신의 인증서를 추가하십시오. 해당 인증서가 길 아래로 만료되면 앱에서 인증서를 업데이트해야합니다. 나는 이것을 할 이유를 생각할 수 없다.
  4. 기본 제공 인증서 KeyStore를 사용하는 사용자 정의 SSLSocketFactory를 작성하십시오. 그러나 기본값으로 확인하지 못한 항목에 대해서는 대체 키 스토어에서 대체합니다.

이 대답은 가장 강력하다고 생각되는 해결책 # 4를 사용합니다.

해결책은 복수의 KeyStores를 받아들이는 SSLSocketFactory를 사용하는 것으로, 독자적인 KeyStore에 독자적인 증명서를 제공 할 수가 있습니다. 이를 통해 일부 Android 장치에서 누락 될 수있는 Thawte와 같은 추가 최상위 인증서를로드 할 수 있습니다. 또한 자체 서명 인증서를로드 할 수도 있습니다. 내장 된 기본 장치 인증서를 먼저 사용하고 필요에 따라 추가 인증서를 사용합니다.

먼저 KeyStore에서 누락 된 인증서를 확인해야합니다. 다음 명령을 실행하십시오.

openssl s_client -connect www.yourserver.com:443

그러면 다음과 같은 출력이 표시됩니다.

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

보시다시피 루트 인증서는 Thawte입니다. 제공 업체의 웹 사이트로 이동하여 해당 인증서를 찾으십시오. 우리에게 그것은 여기 였고 우리는 우리가 필요로했던 것이 저작권 2006 이었음을 알 수 있습니다.

자체 서명 인증서를 사용하는 경우 이미 서명 인증서가 있으므로 이전 단계를 수행 할 필요가 없습니다.

그런 다음 누락 된 서명 인증서가 들어있는 키 저장소 파일을 만듭니다. Crazybob은 안드로이드에서 이것을하는 방법을 자세히 설명합니다 ,하지만 아이디어는 다음을 수행하는 것입니다 :

아직 가지고 있지 않다면 탄력성이 강한 성주 라이브러리를 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

그런 다음, 다음 명령을 실행하여 keystore를 작성하십시오.

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

위 스크립트가 결과를 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);

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

마지막으로 AddKeyStoresSSLSocketFactory 코드는 새로운 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()]);
        }
    }

}
475
emmby

이 코드를 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(); 
    } 
} 

나는 이것이 당신을 돕기를 바랍니다.

66
Alok Gupta

이것은 나쁜 생각입니다. 모든 인증서를 신뢰하는 것은 전혀 SSL을 사용하지 않는 것보다 약간 낫습니다. "하나의 서버를 가리키고 있기 때문에 클라이언트가 인증서를 받아들이 길 원합니다."라고 말하면 "공용 서버가 아닌" "서버 하나"를 가리키는 것이 안전하다는 가정하에 있습니다.

모든 인증서를 신뢰함으로써 man-in-the-middle 공격에 완전히 열려 있습니다. 귀하와 엔드 서버와 별도의 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();

이것은 조심해야 할 하나의 경고가 있습니다. 인증서가 결국 만료되며 코드가 그때 작동하지 않습니다. 인증서를 보면 언제 이런 일이 발생하는지 쉽게 판단 할 수 있습니다.

32
Dan

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

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

위의 코드는 https://stackoverflow.com/a/6378872/1553004 호스트 이름 검증자를 호출해야한다는 점을 제외하고는 정확합니다.

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

이 수정 프로그램을 추가하기 위해 명시 적으로 stackoverflow에 등록했습니다. 내 경고에주의하십시오!

10
Robert Blair

나는 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);
    }
}
}
5
raisercostin

모든 인증서를 신뢰하는 것은 나를 대신 할 수있는 것이 아니므로 HttpsURLConnection에서 새 인증서를 신뢰하게하려면 다음을 수행했습니다 ( http://nelenkov.blogspot.jp/2011/12/using-custom-certificate-trust- store-on.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());
    
4
koljaTM

나는 이것을 사용했고 그것은 모든 OS에서 나를 위해 일한다.

/**
 * 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();
    }
}
3
Baiju Sharma

"emmby"(6 월 16 일 11시 21 분 29 초 응답, 항목 # 4) : "기본 제공 인증서 KeyStore를 사용하지만 실패한 항목에 대해 대체 KeyStore에서 폴링하는 사용자 정의 SSLSocketFactory를 만듭니다. 기본값으로 확인하십시오. "

이것은 단순화 된 구현입니다. 시스템 키 저장소를로드하고 응용 프로그램 키 저장소로 병합하십시오.

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

JKS에서 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

* 참고 : 안드로이드 4.0 (ICS)에서는 트러스트 스토어가 변경되었습니다. 자세한 정보는 다음과 같습니다. http://nelenkov.blogspot.com.es/2011/12/ics-trust-store-implementation.html

3
ggrandes

다음은 4.1.2 httpclient 코드를 사용하여 훨씬 간단한 버전입니다. 그런 다음 적합하다고 생각되는 신뢰 알고리즘으로 수정할 수 있습니다.

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
Joseph Valerio

OAuth를 통해 (테스트 목적으로) 모든 인증서가 작동하도록 허용하려는 사용자는 다음 단계를 따르십시오.

1) Android OAuth API의 소스 코드 다운로드 : https://github.com/kaeppler/signpost

2) "CommonsHttpOAuthProvider"클래스 파일 찾기

3) 아래와 같이 변경하십시오.

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"는 허용 된 답변을 기반으로합니다. 더 쉽게 만들 수 있도록 다음은 전체 클래스입니다.

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

}

희망이 사람을 도움이됩니다.

3
Tiago

VM 인수에 -Dtrust_all_cert=true를 추가하면됩니다. 이 인수는 Java에 인증서 검사를 무시하도록 지시합니다.

1
Ayman Hussain

Android 2.1에서 StartCom SSL 인증서로 여전히 어려움을 겪고있는 모든 기관은 방문 https://www.startssl.com/certs/ 및 다운로드 ca.pem은 이제 @ emmby 에서 제공 한 answer

`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`

 `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`

상자 밖으로 작동해야합니다. 나는 @ emmby .에 의해 완벽한 답을 얻은 후에도 하루 동안 그것을 고투하고 있었다.

0
13hsoj

여기에 이미지 설명을 입력하십시오.

Xamarin Android에서 sspi가 실패했습니다.

나는이 해결책을 발견했다. HTTPS 링크를 누르기 전에이 코드를 넣으십시오.

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

이 클래스를 사용한다.

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
Ali Bagheri