자체 서명 된 인증서로 HTTPS 연결 수락


153

HttpClientlib를 사용하여 HTTPS 연결을 만들려고하는데 문제는 인증서가 Android 신뢰할 수있는 인증서 세트에 나열된 Verisign , GlobalSIgn 등과 같은 공인 인증 기관 (CA)에 의해 서명되지 않았기 때문에 , 나는 계속 받고있다 javax.net.ssl.SSLException: Not trusted server certificate.

모든 인증서를 단순히 수락하는 솔루션을 보았지만 사용자에게 물어 보려면 어떻게해야합니까?

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


이 허용 솔루션은 me-를 위해 일 stackoverflow.com/questions/2642777/...
Venkatesh

답변:


171

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

  • ALLOW_ALL_HOSTNAME_VERIFIER
  • BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
  • STRICT_HOSTNAME_VERIFIER

setHostnameVerifier () 메소드는 새 라이브러리 아파치에는 더 이상 사용되지 않지만 Android SDK의 버전에는 정상입니다. 그래서 우리 ALLOW_ALL_HOSTNAME_VERIFIER는 메소드 팩토리에서 가져 와서 설정합니다 SSLSocketFactory.setHostnameVerifier().

다음으로 프로토콜의 팩토리를 https로 설정해야합니다. 이렇게하려면 단순히 SchemeRegistry.register()메소드 를 호출하십시오 .

그런 다음 DefaultHttpClientwith 을 만들어야합니다 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);

6
이 코드를 불행히도 작동시킬 수는 없지만 여전히 "신뢰할 수없는 서버 인증서"를 얻습니다. 작동하도록 설정해야하는 추가 권한이 있습니까?
Juriy

1
이 코드는 모든 인증서를 수락하지 않습니까? 수락하려면 팝업이 필요합니다.
Morten

3
사용 org.apache.http.conn.ssl.SSLSocketFactory하고 싶은 이유를 사용하고 javax.net.ssl.HttpsURLConnection있습니까 ??
누군가 어딘가에

9
인증서 확인을 완전히 비활성화하는 것보다이 코드가 어떻게 더 나은지 설명 할 수 있습니까? 나는 안드로이드의 ssl API에 익숙하지 않지만 한 눈에 이것은 적극적인 공격자에 대해 완전히 안전하지 않은 것처럼 보입니다.
코드 InChaos

3
SingleClientConnManager 대신 ThreadSafeClientConnManager를 사용하는 것이 좋습니다
Farm

124

안드로이드 플랫폼에서 신뢰할 수없는 것으로 간주되는 인증 기관으로부터 안전하게 연결하려면 다음과 같은 주요 단계가 필요합니다.

많은 사용자의 요청에 따라 블로그 기사 에서 가장 중요한 부분을 여기에 반영했습니다.

  1. 필요한 모든 인증서 (루트 및 중간 CA)를 가져옵니다.
  2. keytool 및 BouncyCastle 제공자를 사용하여 키 저장소를 작성 하고 인증서를 가져 오십시오.
  3. 안드로이드 앱에 키 저장소를로드하고 보안 연결에 사용하십시오 ( 표준 대신 Apache HttpClient 를 사용하는 것이 좋습니다 java.net.ssl.HttpsURLConnection(더 이해하기 쉽고 성능이 좋습니다 )

인증서를 잡아

엔드 포인트 인증서에서 루트 CA까지 체인을 구축하는 모든 인증서를 가져와야합니다. 즉, 중간 CA 인증서 (있는 경우)와 루트 CA 인증서도 있습니다. 엔드 포인트 인증서를 얻을 필요가 없습니다.

키 스토어 작성

BouncyCastle Provider를 다운로드하여 알려진 위치에 저장하십시오. 또한 keytool 명령 (보통 JRE 설치의 bin 폴더 아래에 있음)을 호출 할 수 있는지 확인하십시오.

이제 획득 한 인증서를 엔드 포인트 인증서를 가져 오지 말고 BouncyCastle 형식의 키 저장소로 가져 오십시오.

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

다음 명령을 사용하면 비밀번호가 mysecret 인 새 키 저장소 (아직없는 경우) 가 작성되고 중간 CA 인증서가 가져옵니다. 또한 내 파일 시스템과 키 저장소 형식에서 찾을 수있는 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

인증서를 키 저장소로 올바르게 가져 왔는지 확인하십시오.

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

이제 당신은 아래의 안드로이드 앱에서 키 저장소를 원시 리소스로 복사 할 수 있습니다 res/raw/

앱에서 키 저장소를 사용하십시오.

우선 HTTPS 연결에 키 저장소를 사용하는 사용자 정의 Apache HttpClient를 작성해야합니다.

import org.apache.http.*

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를 만들었습니다. 이제 안전한 연결을 위해 사용할 수 있습니다. 예를 들어 REST 리소스에 대해 GET 호출을하는 경우 :

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

그게 다야;)


8
이것은 응용 프로그램을 배송하기 전에 인증서를 얻는 데만 유용합니다. 사용자가 자신의 인증서를 수락하는 것을 실제로 도와주지는 않습니다. 신청
Fuzzy

안녕 모두 위의 구현을 위해 truststore를 사용하여 키 저장소의 유효성 검사 프로세스를 말해 줄 수 있습니까 ??? 미리 감사드립니다.
andriod_testing 7

이것은 잘 작동했습니다 ..하지만 이제 서버에서 인증서를 다시 입력 할 때 문제가 발생합니다. 서버에서 인증서를 업데이트 할 때마다 클라이언트 쪽 저장소도 업데이트해야하는 것이 이상합니다. 더 좋은 방법이 있어야합니다 : |
bpn

Gr8 답변, SingleClientConnManager 대신 ThreadSafeClientConnManager를 사용하는 것이 좋습니다
Farm

/res/raw/mykeystore.bks대한 참조를 확인할 수는 없지만 추가 했습니다. 이 문제를 해결하는 방법?
uniruddh 2019

16

장치에없는 서버에 사용자 정의 / 자체 서명 인증서가있는 경우 아래 클래스를 사용하여 인증서를로드하고 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의해 사용될 수있는를 생성하는 것 입니다 .HTTPClientHttpsURLConnection
  5. SSLSocketFactory 예를 들어 호스트 이름 확인 등을 건너 뛰도록 추가로 구성 할 수 있습니다.

자세한 정보 : http://developer.android.com/training/articles/security-ssl.html


.crt파일 은 어디서 구할 수 있습니까? 서버에서 다운로드합니까?
zionpi

@zionpi 인증서 파일은 연결중인 TLS 가능 서버에서 사용 된 것과 동일합니다.
SD

감사! 너무 쉬웠다!
kapil thadani

@SD .crt 대신 .P12 파일을 어떻게 사용할 수 있습니까?
Rakesh R Nair

비슷한 의심을 가지고 있습니다. stackoverflow.com/questions/57389622/…
StezPet

8

https를 사용하여 Android 앱을 RESTful 서비스에 연결하려고하는 데 좌절했습니다. 또한 인증서 검사를 모두 비활성화하도록 제안한 모든 답변에 대해 약간 화가났습니다. 그렇게하면 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;
    }
}

내 목업 앱에서 잘 작동했습니다.


Java 또는 javax를 가져와야하는 인증서는 무엇입니까?
Siddharth

내가 수입import java.security.cert.X509Certificate;
Gonzalo Fernández

이 .it에 대한 감사합니다. 그것은 실제로 작동하고 간단합니다
Anuradhe Dilshan

6

최고의 답변은 저에게 효과가 없었습니다. 조사 후 "Android Developer"에 필요한 정보를 찾았습니다. 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 구현은 단지 예일 뿐이며 생산적인 환경에서 사용하면 심각한 보안 위협이 발생할 수 있습니다!


1
단지 fyi-idk 당시에 이와 같았다면, 그들은 지금이 접근법을 강력히 권장하지 않는 것 같습니다 (주 참조)
Saik Caskey

6

구글의 사용을 권장 HTTP / HTTPS 연결을위한 안드로이드 발리를 그 이후 HttpClient사용되지 않습니다. 그래서, 당신은 올바른 선택을 알고 있습니다 :).

또한 NNU SSL 인증서를 절대로 사용하지 마십시오 (NEVER !!!).

SSL 인증서를 핵으로 처리하는 것은 보안을 증진시키는 SSL의 목적과 완전히 반대 입니다. 제공되는 모든 SSL 인증서를 폭격하려는 경우 SSL 사용에 대한 의미가 없습니다. 더 나은 솔루션은 SSL을 사용하지 않거나 더 나은 솔루션 TrustManager은 HTTP / HTTPS 연결을 위해 Android Volley를 사용하여 앱 에서 사용자 지정 을 만드는 것 입니다.

다음 은 기본 LoginApp을 사용하여 서버 측에서 자체 서명 된 인증서를 사용하여 앱에서 허용되는 HTTPS 연결을 수행 하는 요지 입니다.

서버에 설정할 자체 서명 SSL 인증서를 만들고 앱에서 인증서를 사용하는 데 도움이되는 또 다른 요지 도 있습니다. 매우 중요 : 위 스크립트에서 생성 한 .crt 파일을 Android 프로젝트의 "raw"디렉토리로 복사해야합니다.


안녕하세요 Ivan, SSL 인증서를 사용한 적이 없습니다. 조금 더 정교하고 싶습니까? .crt 파일을 어떻게 얻습니까?
jlively

안녕 Jively! 내가 참조. 물론입니다. 그러나 먼저 위에서 언급 한 두 번째 요점을 살펴 보겠습니까? 이 요지에 두 개의 파일을 넣었습니다. 하나는 스크립트에서 사용하는 파일이고 다른 하나는 "openssl"바이너리를 사용하여 파일을 읽은 다음 SSL 인증서가 포함 된 파일을 작성하는 스크립트 자체입니다 ( .crt). 모든 것을 이해했다면 알려주십시오. 감사합니다 :).
ivanleoncz 2016 년

흠 그렇습니다. 나는 그 두 가지 요점을 살펴 보았지만 어떻게 사용하는지 이해할 수 없습니다.
jlively


3

SSL 인증서를 생성하는 가장 간단한 방법

Open Firefox (Chrome에서도 가능하다고 생각하지만 FF를 사용하면 더 쉽습니다)

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

사이트 이름 옆에있는 인증서를 클릭하십시오.

"추가 정보"를 클릭하십시오

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

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

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

"X.509 Certificate whith chain (PEM)"을 선택하고 폴더와 이름을 선택하여 저장 한 다음 "저장"을 클릭하십시오.

pem 파일을 다운로드 한 디렉토리로 명령 행으로 이동하여 "openssl x509 -inform PEM -outform DM -in .pem -out .crt"를 실행하십시오.

.crt 파일을 Android 장치 내 / sdcard 폴더의 루트에 복사합니다. Android 장치 내에서 설정> 보안> 저장소에서 설치.

인증서를 감지하여 장치에 추가 할 수 있도록해야합니다. 개발 사이트를 탐색하십시오.

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

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

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


2

Android 에서 특정 인증서를 신뢰하기 위해 작은 라이브러리 ssl-utils-android 를 작성했습니다.

자산 디렉토리에서 파일 이름을 지정하여 인증서를 간단히로드 할 수 있습니다.

용법:

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

1

SDK 16, 릴리스 4.1.2를 대상으로하는 개발 플랫폼에서는 이러한 수정 프로그램이 작동하지 않으므로 해결 방법을 찾았습니다.

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

최근에 page.php가 " https://www.secure-example.com/page.php " 로 이동했으며 "javax.net.ssl.SSLException : 신뢰할 수없는 서버 인증서"가 계속 표시됩니다.

이 안내서부터 시작 하여 단일 페이지에 대한 모든 인증서를 수락하는 대신 " http://www.example.com/page.php " 에 게시 된 내 자신의 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;
}

?>

1

2020 년 1 월 19 일 자체 서명 인증서 ISSUE FIX :

자체 서명 된 인증서에 대해 비디오, 이미지, 웹 서비스 호출 또는 보안되지 않은 URL에 연결하려면 조치를 수행하기 전에이 메소드를 호출하기 만하면 인증서 문제와 관련된 문제가 해결됩니다.

코 틀린 코드

  private fun disableSSLCertificateChecking() {
        val hostnameVerifier = object: HostnameVerifier {
            override fun verify(s:String, sslSession: SSLSession):Boolean {
                return true
            }
        }
        val trustAllCerts = arrayOf<TrustManager>(object: X509TrustManager {
            override fun getAcceptedIssuers(): Array<X509Certificate> {
                TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
            }

            //val acceptedIssuers:Array<X509Certificate> = null
            @Throws(CertificateException::class)
            override fun checkClientTrusted(arg0:Array<X509Certificate>, arg1:String) {// Not implemented
            }
            @Throws(CertificateException::class)
            override fun checkServerTrusted(arg0:Array<X509Certificate>, arg1:String) {// Not implemented
            }
        })
        try
        {
            val sc = SSLContext.getInstance("TLS")
            sc.init(null, trustAllCerts, java.security.SecureRandom())
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory())
            HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier)
        }
        catch (e: KeyManagementException) {
            e.printStackTrace()
        }
        catch (e: NoSuchAlgorithmException) {
            e.printStackTrace()
        }
    }

0

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

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

HttpClient 라이브러리를 추가하여 Android에서 작동하기를 바랍니다. 행운을 빕니다!


1
아니요 안드로이드 변형에 존재하지 않는 더 이상 사용되지 않는 메소드에 의존하기 때문에 안드로이드에서는 작동하지 않습니다 :-(
kellyfj

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.