문제

다음을 사용하여 HTTPS 연결을 시도하고 있습니다. HttpClient lib이지만 문제는 인증서가 다음과 같이 인정된 인증 기관(CA)에서 서명되지 않았기 때문에 발생합니다. 베리사인,글로벌사인, 등이 Android 신뢰할 수 있는 인증서 세트에 나열되어 있는데 계속해서 javax.net.ssl.SSLException: Not trusted server certificate.

단순히 모든 인증서를 수락하는 솔루션을 본 적이 있지만 사용자에게 물어보고 싶다면 어떻게 해야 할까요?

나는 사용자가 계속할지 여부를 결정할 수 있도록 브라우저와 유사한 대화 상자를 얻고 싶습니다.가급적이면 브라우저와 동일한 인증서 저장소를 사용하고 싶습니다.어떤 아이디어가 있나요?

도움이 되었습니까?

해결책

가장 먼저해야 할 일은 검증 수준을 설정하는 것입니다. 그러한 수준은 그리 많지 않습니다.

  • allow_all_hostname_verifier
  • browser_compatible_hostname_verifier
  • strict_hostname_verifier

SethostNameverifier () 방법은 새로운 라이브러리 Apache의 경우에는 더 이상 사용되지 않지만 Android SDK의 버전은 정상입니다. 그래서 우리는 가져갑니다 ALLOW_ALL_HOSTNAME_VERIFIER 메소드 팩토리에 설정하십시오 SSLSocketFactory.setHostnameVerifier().

다음으로 프로토콜을 HTTP로 설정해야합니다. 이렇게하려면 단순히 전화하십시오 SchemeRegistry.register() 방법.

그런 다음 a를 만들어야합니다 DefaultHttpClient ~와 함께 SingleClientConnManager. 또한 아래 코드에서 기본적으로 우리의 깃발을 사용할 것임을 알 수 있습니다 (ALLOW_ALL_HOSTNAME_VERIFIER) 방법에 의해 HttpsURLConnection.setDefaultHostnameVerifier()

아래 코드는 저를 위해 작동합니다.

HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

DefaultHttpClient client = new DefaultHttpClient();

SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());

// Set verifier     
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

// Example send http request
final String url = "https://encrypted.google.com/";
HttpPost httpPost = new HttpPost(url);
HttpResponse response = httpClient.execute(httpPost);

다른 팁

Android 플랫폼에서 신뢰하는 것으로 간주되지 않는 인증 당국의 보안 연결을 달성하려면 다음 주요 단계가 필요합니다.

많은 사용자가 요청한 바와 같이, 나는 내에서 가장 중요한 부분을 반영했습니다. 블로그 기사 여기:

  1. 필요한 모든 인증서 (루트 및 중간 CA)를 잡습니다.
  2. KeyTool 및 the로 키 스토어를 만듭니다 바운시 캐슬 공급자 및 수입 CERT
  3. Android 앱에 Keystore를로드하여 보안 연결에 사용합니다 (사용하는 것이 좋습니다. 아파치 httpclient 표준 대신 java.net.ssl.HttpsURLConnection (이해하기 쉽고, 더 성능이 더)

세기를 잡아라

엔드 포인트 인증서에서 체인을 구축하는 모든 인증서를 루트 CA까지 가져와야합니다. 이는, 존재하는 경우 중간 CA CERT 및 루트 CA CERT를 의미합니다. 엔드 포인트 인증서를 얻을 필요가 없습니다.

키 스토어를 만듭니다

다운로드 바운시 캐슬 제공 업체 알려진 위치에 보관하십시오. 또한 KeyTool 명령 (일반적으로 JRE 설치의 빈 폴더 아래에 위치)을 호출 할 수 있는지 확인하십시오.

이제 획득 한 CERT (엔드 포인트 인증서를 가져 오지 않음)를 바운시 캐슬 형식의 키 스토어로 가져옵니다.

테스트하지는 않았지만 인증서 가져 오기 순서가 중요하다고 생각합니다. 즉, 최저 중간 CA 인증서를 먼저 가져온 다음 루트 CA 인증서까지 가져옵니다.

다음 명령으로 암호와 함께 새로운 키 스토어 (아직 존재하지 않는 경우) 나의 비밀 생성되고 중간 CA 인증서가 가져옵니다. 또한 파일 시스템과 Keystore 형식에서 찾을 수있는 Bouncycastle 제공 업체를 정의했습니다. 체인에서 각 인증서에 대해이 명령을 실행하십시오.

keytool -importcert -v -trustcacerts -file "path_to_cert/interm_ca.cer" -alias IntermediateCA -keystore "res/raw/myKeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret

인증서가 Keystore로 올바르게 가져온지 확인하십시오.

keytool -list -keystore "res/raw/myKeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "path_to_bouncycastle/bcprov-jdk16-145.jar" -storetype BKS -storepass mysecret

전체 체인을 출력해야합니다.

RootCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 24:77:D9:A8:91:D1:3B:FA:88:2D:C2:FF:F8:CD:33:93
IntermediateCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 98:0F:C3:F8:39:F7:D8:05:07:02:0D:E3:14:5B:29:43

이제 KeyStore를 Android 앱에서 원료로 복사 할 수 있습니다. res/raw/

앱에서 키 스토어를 사용하십시오

우선 HTTPS 연결에 키 스토어를 사용하는 사용자 정의 apache httpclient를 만들어야합니다.

public class MyHttpClient extends DefaultHttpClient {

  final Context context;

  public MyHttpClient(Context context) {
      this.context = context;
  }

  @Override
  protected ClientConnectionManager createClientConnectionManager() {
      SchemeRegistry registry = new SchemeRegistry();
      registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
      // Register for port 443 our SSLSocketFactory with our keystore
      // to the ConnectionManager
      registry.register(new Scheme("https", newSslSocketFactory(), 443));
      return new SingleClientConnManager(getParams(), registry);
  }

  private SSLSocketFactory newSslSocketFactory() {
      try {
          // Get an instance of the Bouncy Castle KeyStore format
          KeyStore trusted = KeyStore.getInstance("BKS");
          // Get the raw resource, which contains the keystore with
          // your trusted certificates (root and any intermediate certs)
          InputStream in = context.getResources().openRawResource(R.raw.mykeystore);
          try {
              // Initialize the keystore with the provided trusted certificates
              // Also provide the password of the keystore
              trusted.load(in, "mysecret".toCharArray());
          } finally {
              in.close();
          }
          // Pass the keystore to the SSLSocketFactory. The factory is responsible
          // for the verification of the server certificate.
          SSLSocketFactory sf = new SSLSocketFactory(trusted);
          // Hostname verification from certificate
          // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
          sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
          return sf;
      } catch (Exception e) {
          throw new AssertionError(e);
      }
  }
}

우리는 맞춤형 httpclient를 만들었습니다. 이제 안전한 연결에 사용할 수 있습니다. 예를 들어 휴식 자원을 호출 할 때.

// Instantiate the custom HttpClient
DefaultHttpClient client = new MyHttpClient(getApplicationContext());
HttpGet get = new HttpGet("https://www.mydomain.ch/rest/contacts/23");
// Execute the GET call and obtain the response
HttpResponse getResponse = client.execute(get);
HttpEntity responseEntity = getResponse.getEntity();

그게 다야;)

서버에는 사용자 정의/자체 서명된 인증서가 있는 경우 아래 클래스를 사용하여 이를 로드하고 Android의 클라이언트 측에서 사용할 수 있습니다.

인증서를 배치 *.crt 제출하다 /res/raw 그래서 그것은에서 사용할 수 있습니다 R.raw.*

아래 클래스를 사용하여 HTTPClient 또는 HttpsURLConnection 해당 인증서를 사용하는 소켓 팩토리가 있습니다.

package com.example.customssl;

import android.content.Context;
import org.apache.http.client.HttpClient;
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.AllowAllHostnameVerifier;
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 javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;

public class CustomCAHttpsProvider {

    /**
     * Creates a {@link org.apache.http.client.HttpClient} which is configured to work with a custom authority
     * certificate.
     *
     * @param context       Application Context
     * @param certRawResId  R.raw.id of certificate file (*.crt). Should be stored in /res/raw.
     * @param allowAllHosts If true then client will not check server against host names of certificate.
     * @return Http Client.
     * @throws Exception If there is an error initializing the client.
     */
    public static HttpClient getHttpClient(Context context, int certRawResId, boolean allowAllHosts) throws Exception {


        // build key store with ca certificate
        KeyStore keyStore = buildKeyStore(context, certRawResId);

        // init ssl socket factory with key store
        SSLSocketFactory sslSocketFactory = new SSLSocketFactory(keyStore);

        // skip hostname security check if specified
        if (allowAllHosts) {
            sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier());
        }

        // basic http params for client
        HttpParams params = new BasicHttpParams();

        // normal scheme registry with our ssl socket factory for "https"
        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));

        // create connection manager
        ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);

        // create http client
        return new DefaultHttpClient(cm, params);
    }

    /**
     * Creates a {@link javax.net.ssl.HttpsURLConnection} which is configured to work with a custom authority
     * certificate.
     *
     * @param urlString     remote url string.
     * @param context       Application Context
     * @param certRawResId  R.raw.id of certificate file (*.crt). Should be stored in /res/raw.
     * @param allowAllHosts If true then client will not check server against host names of certificate.
     * @return Http url connection.
     * @throws Exception If there is an error initializing the connection.
     */
    public static HttpsURLConnection getHttpsUrlConnection(String urlString, Context context, int certRawResId,
                                                           boolean allowAllHosts) throws Exception {

        // build key store with ca certificate
        KeyStore keyStore = buildKeyStore(context, certRawResId);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        // Create an SSLContext that uses our TrustManager
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);

        // Create a connection from url
        URL url = new URL(urlString);
        HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
        urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());

        // skip hostname security check if specified
        if (allowAllHosts) {
            urlConnection.setHostnameVerifier(new AllowAllHostnameVerifier());
        }

        return urlConnection;
    }

    private static KeyStore buildKeyStore(Context context, int certRawResId) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
        // init a default key store
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);

        // read and add certificate authority
        Certificate cert = readCert(context, certRawResId);
        keyStore.setCertificateEntry("ca", cert);

        return keyStore;
    }

    private static Certificate readCert(Context context, int certResourceId) throws CertificateException, IOException {

        // read certificate resource
        InputStream caInput = context.getResources().openRawResource(certResourceId);

        Certificate ca;
        try {
            // generate a certificate
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            ca = cf.generateCertificate(caInput);
        } finally {
            caInput.close();
        }

        return ca;
    }

}

키 포인트:

  1. Certificate 객체는 다음에서 생성됩니다. .crt 파일.
  2. 기본값 KeyStore 생성됩니다.
  3. keyStore.setCertificateEntry("ca", cert) 별칭 "ca"로 키 저장소에 인증서를 추가하고 있습니다.더 많은 인증서(중간 CA 등)를 추가하려면 코드를 수정합니다.
  4. 주요 목표는 SSLSocketFactory 그런 다음 다음에서 사용할 수 있습니다. HTTPClient 또는 HttpsURLConnection.
  5. SSLSocketFactory 예를 들어 호스트 이름 확인을 건너뛰도록 추가로 구성할 수 있습니다.

자세한 내용은 다음을 참조하세요. http://developer.android.com/training/articles/security-ssl.html

최고 답변은 저에게 효과가 없었습니다. 일부 조사 후 "Android 개발자"에 대한 필요한 정보를 찾았습니다.https://developer.android.com/training/articles/security-ssl.html#selfsigned

x509trustmanager의 빈 구현을 만들었습니다.

private static class MyTrustManager implements 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;
    }

}

...

HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
try
{
    // Create an SSLContext that uses our TrustManager
    SSLContext context = SSLContext.getInstance("TLS");
    TrustManager[] tmlist = {new MyTrustManager()};
    context.init(null, tmlist, null);
    conn.setSSLSocketFactory(context.getSocketFactory());
}
catch (NoSuchAlgorithmException e)
{
    throw new IOException(e);
} catch (KeyManagementException e)
{
    throw new IOException(e);
}
conn.setRequestMethod("GET");
int rcode = conn.getResponseCode();

Tustmanager 의이 빈 구현은 예제 일 뿐이며 생산적인 환경에서이를 사용하면 심각한 보안 위협이 발생할 수 있습니다!

HTTPS를 사용하여 Android 앱을 편안한 서비스에 연결하려고 노력하는 데 좌절했습니다. 또한 나는 인증서 점검을 비활성화하기 위해 제안한 모든 답변에 대해 약간 짜증이났습니다. 그렇게한다면 HTTPS의 요점은 무엇입니까?

한동안 주제에 대해 Googled 후 마침내 이것 솔루션 외부 항아리가 필요하지 않은 경우 Android API. 2014 년 7 월에 게시 한 Andrew Smith에게 감사드립니다.

 /**
 * Set up a connection to myservice.domain using HTTPS. An entire function
 * is needed to do this because myservice.domain has a self-signed certificate.
 * 
 * The caller of the function would do something like:
 * HttpsURLConnection urlConnection = setUpHttpsConnection("https://littlesvr.ca");
 * InputStream in = urlConnection.getInputStream();
 * And read from that "in" as usual in Java
 * 
 * Based on code from:
 * https://developer.android.com/training/articles/security-ssl.html#SelfSigned
 */
public static HttpsURLConnection setUpHttpsConnection(String urlString)
{
    try
    {
        // Load CAs from an InputStream
        // (could be from a resource or ByteArrayInputStream or ...)
        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        // My CRT file that I put in the assets folder
        // I got this file by following these steps:
        // * Go to https://littlesvr.ca using Firefox
        // * Click the padlock/More/Security/View Certificate/Details/Export
        // * Saved the file as littlesvr.crt (type X.509 Certificate (PEM))
        // The MainActivity.context is declared as:
        // public static Context context;
        // And initialized in MainActivity.onCreate() as:
        // MainActivity.context = getApplicationContext();
        InputStream caInput = new BufferedInputStream(MainActivity.context.getAssets().open("littlesvr.crt"));
        Certificate ca = cf.generateCertificate(caInput);
        System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());

        // Create a KeyStore containing our trusted CAs
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        // Create an SSLContext that uses our TrustManager
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, tmf.getTrustManagers(), null);

        // Tell the URLConnection to use a SocketFactory from our SSLContext
        URL url = new URL(urlString);
        HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
        urlConnection.setSSLSocketFactory(context.getSocketFactory());

        return urlConnection;
    }
    catch (Exception ex)
    {
        Log.e(TAG, "Failed to establish SSL connection to server: " + ex.toString());
        return null;
    }
}

Mockup 앱에서 잘 작동했습니다.

Google은 사용을 권장합니다 HTTP/HTTPS 연결 용 Android Volley, 그때 이후로 HttpClient 더 이상 사용되지 않습니다. 그래서 당신은 올바른 선택을 알고 있습니다 :).

그리고 또한, 절대로 SSL 인증서를 절대로하지 마십시오 (절대 !!!).

Nuke SSL 인증서는 전적으로 홍보중인 SSL의 목적에 위배됩니다. 보안. 모든 SSL 인증서를 폭파 할 계획이라면 SSL을 사용한다는 느낌이 없습니다. 더 나은 솔루션은 SSL을 사용하지 않거나 더 나은 솔루션이 사용자 정의를 만드는 것입니다. TrustManager 앱에서 http/https 연결에 Android Volley를 사용합니다.

여기에 있습니다 요점 기본 LoginApp을 사용하여 HTTPS 연결을 수행하고 서버 측에서 자체 서명 된 인증서를 사용하여 앱에서 수락했습니다.

여기에 또 다른 것입니다 요점 이는 서버에서 설정하기위한 자체 서명 된 SSL 인증서를 작성하고 앱에서 인증서를 사용하는 데 도움이 될 수 있습니다. 매우 중요: 위의 스크립트에서 생성 된 .CRT 파일을 Android 프로젝트의 "RAW"디렉토리에 복사해야합니다.

이 문제를 피하기 위해 Keystore에 추가 인증서를 추가하는 방법은 다음과 같습니다. httpclient를 사용하여 HTTPS를 통해 모든 인증서를 신뢰합니다

사용자가 요청하는 것처럼 사용자에게 촉구되지는 않지만 사용자가 "신뢰할 수없는 서버 인증서"오류가 발생할 가능성이 적습니다.

SSL 인증서를 만드는 가장 간단한 방법

Open Firefox (Chrome에서도 가능하지만 FF에서는 더 쉽다고 생각합니다).

자체 서명 된 SSL 인증서와 함께 개발 사이트를 방문하십시오.

인증서를 클릭하십시오 (사이트 이름 옆)

"자세한 정보"를 클릭하십시오.

"인증서보기"를 클릭하십시오.

"세부 사항"을 클릭하십시오.

"내보내기 ..."를 클릭하십시오.

"X.509 인증서 Whith Chain (PEM)"을 선택하고 폴더 및 이름을 선택하여 저장하고 "저장"을 클릭하십시오.

PEM 파일을 다운로드 한 디렉토리로 이동하고 "OpenSSL X509 -Inform Pem -outform DM -in .pem -out .crt"를 실행하는 디렉토리로 이동하십시오.

.crt 파일을 Android 장치 내부의 Android 장치 내부의 /sdcard 폴더의 루트로 복사하십시오. 설정> 보안> 스토리지에서 설치하십시오.

인증서를 감지하고 개발 사이트에 장치 찾아에 추가해야합니다.

처음으로 보안 예외를 확인하도록 요청해야합니다. 그게 다야.

인증서는 Android (브라우저, Chrome, Opera, Dolphin ...)에 설치된 모든 브라우저와 함께 작동해야합니다.

다른 도메인에서 정적 파일을 제공하는 경우 (우리 모두 페이지 속도 암캐 임) 해당 도메인의 인증서를 추가해야합니다.

나는 작은 도서관을 썼다 SSL-utils-Android Android에서 특정 인증서를 신뢰합니다.

자산 디렉토리에서 파일 이름을 제공하여 모든 인증서를로드 할 수 있습니다.

용법:

OkHttpClient client = new OkHttpClient();
SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer");
client.setSslSocketFactory(sslContext.getSocketFactory());

이 수정 사항 중 어느 것도 SDK 16을 타겟팅하는 플랫폼 개발에 적합하지 않았으므로 해결 방법을 찾았습니다.

내 앱은 "사용"서버에 데이터를 저장합니다.http://www.example.com/page.php?data=somedata"

최근 page.php가 "로 옮겨졌다"https://www.secure-example.com/page.php"그리고 나는 계속 받고있다"javax.net.ssl.sslexception : 신뢰할 수있는 서버 인증서가 아니다 ".

단일 페이지에 대해서만 모든 인증서를 수락하는 대신 이 가이드부터 시작합니다 내 자신의 page.php를 작성하는 문제를 해결했습니다.http://www.example.com/page.php"

<?php

caronte ("https://www.secure-example.com/page.php");

function caronte($url) {
    // build curl request
    $ch = curl_init();
    foreach ($_POST as $a => $b) {
        $post[htmlentities($a)]=htmlentities($b);
    }
    curl_setopt($ch, CURLOPT_URL,$url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($post));

    // receive server response ...
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $server_output = curl_exec ($ch);
    curl_close ($ch);

    echo $server_output;
}

?>

어쩌면 이것은 도움이 될 것입니다 ... 자체 서명 인증서를 사용하여 Java 클라이언트에서 작동합니다 (인증서는 없습니다). 조심하고 개발 사례에만 사용하십시오. 왜냐하면 그것은 전혀 안전하지 않기 때문입니다 !!

Apache httpclient 4.0에서 SSL 인증서 오류를 무시하는 방법

httpclient 라이브러리를 추가하는 것만으로도 안드로이드에서 작동하기를 바랍니다. 행운을 빕니다 !!

이것은 SNI 부족 (서버 이름 식별)이 NDroid 2.X를 지원하는 문제입니다. 나는 다음 질문을 발견 할 때까지 일주일 동안이 문제로 어려움을 겪고있었습니다.이 질문은 문제의 좋은 배경을 제공 할뿐만 아니라 보안 구멍이없는 작동하고 효과적인 솔루션을 제공합니다.

Android 2.3에서 '피어 인증서'오류가 있지만 4는 아닙니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top