[java] Https 연결 Android

https 게시물을 작성하고 있는데 SSL 예외가 아닌 신뢰할 수없는 서버 인증서 예외가 발생합니다. 내가 정상적인 http를하면 완벽하게 잘 작동합니다. 어떻게 든 서버 인증서를 수락해야합니까?



답변

추측하고 있지만 실제 핸드 셰이크가 발생하려면 Android에 인증서를 알려야합니다. 무엇이든 받아들이고 싶다면 다음 의사 코드를 사용하여 Apache HTTP 클라이언트에서 필요한 것을 얻으십시오.

SchemeRegistry schemeRegistry = new SchemeRegistry ();

schemeRegistry.register (new Scheme ("http",
    PlainSocketFactory.getSocketFactory (), 80));
schemeRegistry.register (new Scheme ("https",
    new CustomSSLSocketFactory (), 443));

ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager (
    params, schemeRegistry);


return new DefaultHttpClient (cm, params);

CustomSSLSocketFactory :

public class CustomSSLSocketFactory extends org.apache.http.conn.ssl.SSLSocketFactory
{
private SSLSocketFactory FACTORY = HttpsURLConnection.getDefaultSSLSocketFactory ();

public CustomSSLSocketFactory ()
    {
    super(null);
    try
        {
        SSLContext context = SSLContext.getInstance ("TLS");
        TrustManager[] tm = new TrustManager[] { new FullX509TrustManager () };
        context.init (null, tm, new SecureRandom ());

        FACTORY = context.getSocketFactory ();
        }
    catch (Exception e)
        {
        e.printStackTrace();
        }
    }

public Socket createSocket() throws IOException
{
    return FACTORY.createSocket();
}

 // TODO: add other methods like createSocket() and getDefaultCipherSuites().
 // Hint: they all just make a call to member FACTORY 
}

FullX509TrustManager는 javax.net.ssl.X509TrustManager를 구현하는 클래스이지만 실제로 작업을 수행하는 메소드는 없습니다 . 여기 에서 샘플을 얻으 십시오 .

행운을 빕니다!


답변

이것이 내가하는 일입니다. 더 이상 인증서를 확인하지 않습니다.

// always verify the host - dont check for certificate
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
};

/**
 * Trust every server - dont check for any certificate
 */
private static void trustAllHosts() {
    // Create a trust manager that does not validate certificate chains
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[] {};
        }

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

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

    // Install the all-trusting trust manager
    try {
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection
                .setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

    HttpURLConnection http = null;

    if (url.getProtocol().toLowerCase().equals("https")) {
        trustAllHosts();
        HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
        https.setHostnameVerifier(DO_NOT_VERIFY);
        http = https;
    } else {
        http = (HttpURLConnection) url.openConnection();
    }


답변

이 질문에 답하는 동안 더 나은 튜토리얼을 찾았습니다. 그것으로 당신은 인증서 검사를 손상시킬 필요가 없습니다.

http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

* 저는이 글을 쓰지 않았지만 작업을 해주신 Bob Lee에게 감사드립니다.


답변

crazybobs와 매우 유사한 내 블로그 기사를 볼 수도 있습니다.

이 솔루션은 또한 인증서 검사를 손상시키지 않으며 자체 키 저장소에 신뢰할 수있는 인증서를 추가하는 방법을 설명합니다.

http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/


답변

http://madurangasblogs.blogspot.in/2013/08/avoiding-javaxnetsslsslpeerunverifiedex.html

의례 Maduranga

https를 사용하는 애플리케이션을 개발할 때 테스트 서버에 유효한 SSL 인증서가 없습니다. 또는 웹 사이트에서 자체 서명 된 인증서를 사용하거나 웹 사이트에서 무료 SSL 인증서를 사용하는 경우가 있습니다. 따라서 Apache를 사용하여 서버에 연결하려고 HttpClient하면 “peer not authenticated”라는 예외가 발생합니다. 프로덕션 소프트웨어의 모든 인증서를 신뢰하는 것은 좋지 않지만 상황에 따라 그렇게해야 할 수도 있습니다. 이 솔루션은 “피어가 인증되지 않음”으로 인한 예외를 해결합니다.

그러나 솔루션으로 이동하기 전에 이것은 프로덕션 응용 프로그램에 좋은 아이디어가 아니라는 점을 경고해야합니다. 이는 보안 인증서 사용 목적에 위배됩니다. 따라서 정당한 이유가 있거나 이것이 문제를 일으키지 않는다고 확신하는 경우가 아니면이 솔루션을 사용하지 마십시오.

일반적으로 다음 HttpClient과 같이 만듭니다 .

HttpClient httpclient = new DefaultHttpClient();

그러나 HttpClient를 만드는 방법을 변경해야합니다.

먼저 org.apache.http.conn.ssl.SSLSocketFactory.

import org.apache.http.conn.ssl.SSLSocketFactory;
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;

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

그런 다음 이와 같은 방법을 만듭니다.

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

그런 다음 HttpClient.

HttpClient httpclient = getNewHttpClient();

로그인 페이지에 게시 요청을 보내려는 경우 나머지 코드는 다음과 같습니다.

private URI url = new URI("url of the action of the form");
HttpPost httppost =  new HttpPost(url);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("username", "user"));
nameValuePairs.add(new BasicNameValuePair("password", "password"));
try {
    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
    HttpResponse response = httpclient.execute(httppost);
    HttpEntity entity = response.getEntity();
    InputStream is = entity.getContent();
} catch (UnsupportedEncodingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (ClientProtocolException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

InputStream에 html 페이지를 가져옵니다. 그런 다음 반환 된 html 페이지로 원하는 것을 할 수 있습니다.

그러나 여기서 문제에 직면하게 될 것입니다. 쿠키를 사용하여 세션을 관리하려는 경우이 방법으로는 수행 할 수 없습니다. 쿠키를 얻으려면 브라우저를 통해해야합니다. 그러면 귀하 만 쿠키를 받게됩니다.


답변

StartSSL 또는 Thawte 인증서를 사용하는 경우 Froyo 및 이전 버전에서는 실패합니다. 모든 인증서를 신뢰하는 대신 최신 버전의 CAcert 저장소 를 사용할 수 있습니다 .


답변

이것들 중 어느 것도 나를 위해 일하지 않았습니다 ( Thawte 버그 로 인해 악화되었습니다 ). 결국 나는 그것이 고정있어 안드로이드에 대한 자체 서명 된 SSL 수용사용자 정의 SSL 처리는 안드로이드 2.2 프로 요에 작동이 중지