स्व-हस्ताक्षरित प्रमाण पत्र के साथ HTTPS कनेक्शन स्वीकार करना


153

मैं HTTPS कनेक्शन बनाने के लिए कोशिश कर रहा हूँ का उपयोग कर, HttpClientलिब, के बाद से प्रमाणपत्र किसी मान्य प्रमाणपत्र प्राधिकारी (CA) की तरह द्वारा हस्ताक्षरित नहीं है, लेकिन समस्या यह है कि है Verisign , ग्लोबलसाइन , आदि, एंड्रॉयड विश्वसनीय प्रमाण पत्र के सेट पर सूचीबद्ध, मैं मिलता रहा javax.net.ssl.SSLException: Not trusted server certificate

मैंने ऐसे समाधान देखे हैं जहाँ आप सभी प्रमाणपत्रों को स्वीकार करते हैं, लेकिन अगर मैं उपयोगकर्ता से पूछना चाहता हूँ तो क्या होगा?

मैं ब्राउज़र के समान एक संवाद प्राप्त करना चाहता हूं, जिससे उपयोगकर्ता को जारी रखने या न करने का निर्णय लिया जा सके। अधिमानतः मैं ब्राउज़र के रूप में एक ही प्रमाणपत्र का उपयोग करना चाहूंगा। कोई विचार?


इस स्वीकृत समाधान ने मेरे लिए काम किया- stackoverflow.com/questions/2642777/…
वेंकटेश

जवाबों:


171

पहली चीज जो आपको करने की ज़रूरत है वह है सत्यापन का स्तर निर्धारित करना। ऐसा स्तर इतना नहीं है:

  • ALLOW_ALL_HOSTNAME_VERIFIER
  • BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
  • STRICT_HOSTNAME_VERIFIER

हालांकि नई लाइब्रेरी अपाचे के लिए मेथड सेटहोस्टनाम वीरिफायर () अप्रचलित है, लेकिन एंड्रॉइड एसडीके में संस्करण सामान्य है। और इसलिए हम ALLOW_ALL_HOSTNAME_VERIFIERइसे विधि कारखाने में लेते हैं और सेट करते हैं SSLSocketFactory.setHostnameVerifier()

अगला, आपको प्रोटोकॉल के लिए हमारे कारखाने को https में सेट करने की आवश्यकता है। ऐसा करने के लिए, बस कॉल करेंSchemeRegistry.register() विधि को ।

फिर आपको एक 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);

6
मैं इस कोड को दुर्भाग्य से काम नहीं कर सकता, मुझे अभी भी "विश्वसनीय सर्वर प्रमाणपत्र नहीं" मिला है। क्या कोई अतिरिक्त अनुमतियाँ हैं जो मुझे काम करने के लिए निर्धारित करनी हैं?
जूरि

1
क्या यह कोड सभी प्रमाणपत्रों को स्वीकार नहीं करता है? मुझे इसे स्वीकार करने के लिए एक पॉपअप चाहिए।
मोर्टेन

3
मैं उपयोग कर रहा हूँ org.apache.http.conn.ssl.SSLSocketFactoryक्यों मैं उपयोग करना चाहते हैं javax.net.ssl.HttpsURLConnection??
किसी ने 14:30

9
क्या आप बता सकते हैं कि यह कोड पूरी तरह से प्रमाणपत्र सत्यापन को अक्षम करने से बेहतर कैसे है? मैं एंड्रॉइड के एसएसएल एपीआई से परिचित नहीं हूं, लेकिन एक नज़र में यह सक्रिय हमलावरों के खिलाफ पूरी तरह असुरक्षित लगता है।
कोडइन्चोस

3
मैं SingleClientConnManager के बजाय ThreadSafeClientConnManager का उपयोग करने का सुझाव दूंगा
फार्म

124

प्रमाणन प्लेटफ़ॉर्म से सुरक्षित कनेक्शन प्राप्त करने के लिए निम्नलिखित मुख्य चरणों की आवश्यकता होती है, जिन्हें एंड्रॉइड प्लेटफॉर्म द्वारा विश्वसनीय नहीं माना जाता है।

जैसा कि कई उपयोगकर्ताओं द्वारा अनुरोध किया गया है, मैंने अपने ब्लॉग लेख के सबसे महत्वपूर्ण हिस्सों को यहाँ दिखाया है:

  1. सभी आवश्यक प्रमाणपत्र (मूल और किसी भी मध्यवर्ती सीए के) को पकड़ो
  2. Keytool और BouncyCastle प्रदाता के साथ एक कीस्टोर बनाएँ और सीट्स आयात करें
  3. अपने एंड्रॉइड ऐप में कीस्टोर को लोड करें और इसे सुरक्षित कनेक्शन के लिए उपयोग करें (मैं मानक के बजाय Apache HttpClient का उपयोग करने की सलाह देता हूं java.net.ssl.HttpsURLConnection(समझने में आसान, अधिक प्रदर्शन करने वाला)

अनाज पकड़ो

आपको उन सभी प्रमाणपत्रों को प्राप्त करना होगा जो एक समापन बिंदु प्रमाण पत्र से एक श्रृंखला बनाते हैं रूट सीए तक। इसका मतलब है, कोई भी (यदि मौजूद है) इंटरमीडिएट सीए सेर्ट करता है और रूट सीए सर्टिफिकेट भी। आपको समापन बिंदु प्रमाणपत्र प्राप्त करने की आवश्यकता नहीं है।

कीस्टोर बनाएँ

BouncyCastle प्रदाता डाउनलोड करें और इसे किसी ज्ञात स्थान पर संग्रहीत करें। यह भी सुनिश्चित करें कि आप keytool कमांड (आमतौर पर आपके JRE इंस्टॉलेशन के बिन फ़ोल्डर के नीचे स्थित) को लागू कर सकते हैं।

अब BouncyCastle स्वरूपित कीस्टोर में प्राप्त किए गए सीट्स (समापन बिंदु प्रमाणपत्र को आयात न करें) आयात करें।

मैंने इसका परीक्षण नहीं किया, लेकिन मुझे लगता है कि प्रमाणपत्र आयात करने का क्रम महत्वपूर्ण है। इसका मतलब है, सबसे पहले इंटरमीडिएट सीए प्रमाण पत्र को आयात करें और फिर रूट सीए प्रमाणपत्र तक सभी तरह से।

निम्नलिखित कमांड के साथ पासवर्ड के साथ एक नया कीस्टोर (यदि पहले से मौजूद नहीं है) 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

अब आप अपने Android ऐप में कच्चे संसाधन के रूप में कीस्टोर को कॉपी कर सकते हैं res/raw/

अपने ऐप में कीस्टोर का इस्तेमाल करें

सबसे पहले हमें एक कस्टम Apache HttpClient बनाना होगा जो HTTPS कनेक्शन के लिए हमारे कीस्टोर का उपयोग करता है:

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
यह केवल आपके आवेदन के शिपिंग से पहले प्रमाण पत्र प्राप्त करने के लिए उपयोगी है। वास्तव में उपयोगकर्ताओं को अपने स्वयं के अनाज को स्वीकार करने में मदद नहीं करता है। आपके आवेदन के लिए
फजी

हाय सब कुछ मुझे ऊपर कार्यान्वयन के लिए ट्रस्टस्टोर के साथ कीस्टोर के लिए सत्यापन प्रक्रिया बता सकते हैं ??? अग्रिम धन्यवाद ..
andriod_testing

यह ठीक काम किया है..लेकिन अब मैं एक समस्या का सामना कर रहा हूं जब मैं सर्वर पर प्रमाण पत्र को फिर से जोड़ता हूं। यह अजीब लगता है कि हर बार मैं अपने सर्वर पर प्रमाण पत्र को अपडेट करता हूं, क्लाइंट साइड स्टोर को भी अपडेट किया जाना चाहिए। एक बेहतर तरीका है: |
bpn

Gr8 उत्तर, मैं सिंगल क्लींटकॉन्नेमैन के बजाय थ्रेडसेफ़्लिएंटकोनमैनेजर का उपयोग करने का सुझाव दूंगा
फार्म

मैंने जोड़ा है /res/raw/mykeystore.bks, हालांकि इसके संदर्भ को हल करने में असमर्थ है। इसे कैसे हल किया जाए?
अनिरुद्ध

16

यदि आपके पास सर्वर पर कस्टम / स्व-हस्ताक्षरित प्रमाणपत्र है जो डिवाइस पर नहीं है, तो आप इसे लोड करने के लिए निम्न वर्ग का उपयोग कर सकते हैं और एंड्रॉइड में क्लाइंट साइड पर इसका उपयोग कर सकते हैं:

प्रमाण पत्र *.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 आदि) जोड़ने के लिए कोड को संशोधित करते हैं।
  4. मुख्य उद्देश्य एक उत्पन्न करने के लिए है SSLSocketFactoryजो तब तक इस्तेमाल किया जा सकता HTTPClientया HttpsURLConnection
  5. SSLSocketFactory आगे कॉन्फ़िगर किया जा सकता है, उदाहरण के लिए मेजबान नाम सत्यापन को छोड़ दें आदि।

अधिक जानकारी: http://developer.android.com/training/articles/security-ssl.html


मुझे .crtफ़ाइलें कहाँ मिल सकती हैं ? एक सर्वर से डाउनलोड करें?
zionpi

@zionpi प्रमाणपत्र फ़ाइल उसी TLS सक्षम सर्वर द्वारा उपयोग की जाएगी जो आप कनेक्ट कर रहे हैं।
एसडी

धन्यवाद! यह इतना आसान था!
कपिल थडानी

@SD मैं .crt के बजाय .P12 फ़ाइल का उपयोग कैसे कर सकता हूं?
राकेश आर नायर

मेरे पास एक समान संदेह है कि आप कृपया stackoverflow.com/questions/57389622/…
StezPet

8

मैं https का उपयोग करके अपने Android ऐप को मेरी RESTful सेवा से जोड़ने की कोशिश कर रहा था। इसके अलावा, मैं उन सभी उत्तरों के बारे में थोड़ा परेशान था, जिन्होंने प्रमाणपत्र जाँच को पूरी तरह से अक्षम करने का सुझाव दिया था। यदि आप ऐसा करते हैं, तो https का क्या मतलब है?

थोड़ी देर के लिए विषय के बारे में गुगली करने के बाद, मुझे आखिरकार यह समाधान मिला जहां बाहरी जार की आवश्यकता नहीं है, बस एंड्रॉइड एपीआई। एंड्रयू स्मिथ का शुक्रिया, जिन्होंने इसे जुलाई, 2014 को पोस्ट किया

 /**
 * 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;
    }
}

इसने मेरे मॉकअप ऐप के लिए अच्छा काम किया।


X509 सर्टिफिकेट जो मुझे java या javax आयात करना चाहिए?
सिद्धार्थ

मैंने आयात कियाimport java.security.cert.X509Certificate;
फर्नांडीज

इसके लिए धन्यवाद। यह वास्तव में काम और सरल है
अनुराधा दिलशान

6

शीर्ष जवाब मेरे लिए काम नहीं किया। कुछ जांच के बाद मुझे "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 का यह खाली कार्यान्वयन केवल एक उदाहरण है और इसे उत्पादक वातावरण में उपयोग करने से सुरक्षा के लिए गंभीर खतरा पैदा होगा!


1
बस फि - इद अगर यह उस समय ऐसा था, लेकिन वे इस दृष्टिकोण को दृढ़ता से हतोत्साहित करते हैं (नोट देखें)
Saik Caskey

6

Google HTTP / HTTPS कनेक्शन के लिए Android वॉली के उपयोग की सिफारिश करता है , क्योंकि HttpClientयह पदावनत है। तो, आप सही विकल्प जानते हैं :)।

और भी, कभी NUKE SSL प्रमाणपत्र (कभी नहीं !!!)।

SSL प्रमाणपत्र को एनक्यूई करने के लिए, पूरी तरह से एसएसएल के उद्देश्य के खिलाफ है, जो सुरक्षा को बढ़ावा दे रहा है । SSL का उपयोग करने का कोई मतलब नहीं है, यदि आप आने वाले सभी एसएसएल प्रमाणपत्रों को बम बनाने की योजना बना रहे हैं। एक बेहतर समाधान, एसएसएल का उपयोग न करना या एक बेहतर समाधान होगा, यह TrustManagerआपके ऐप + पर HTTP / HTTPS कनेक्शन के लिए एंड्रॉइड वॉली का उपयोग करके एक कस्टम बना देगा ।

यहाँ एक है सार एक बुनियादी LoginApp साथ जो मेरे द्वारा बनाए गए, HTTPS कनेक्शन, सर्वर साइड पर एक स्व-हस्ताक्षरित प्रमाणपत्र, अनुप्रयोग पर स्वीकार किए जाते हैं का उपयोग कर प्रदर्शन करते हुए।

आपके सर्वर पर स्थापित करने के लिए और अपने ऐप पर प्रमाणपत्र का उपयोग करने के लिए स्व-हस्ताक्षरित एसएसएल प्रमाणपत्र बनाने में मदद करने के लिए एक और जिस्ट भी यहां दिया गया है।बहुत महत्वपूर्ण: आपको अपने एंड्रॉइड प्रोजेक्ट से "कच्चे" निर्देशिका के लिए .crt फ़ाइल को ऊपर लिपि द्वारा जनरेट किया जाना चाहिए।


हैलो इवान, मैंने SSL प्रमाणपत्र के साथ कभी काम नहीं किया है। क्या आप थोड़ा विस्तार से ध्यान देंगे, मुझे .crt फ़ाइल कैसे मिलेगी?
jlively

हाय जलील! समझा। हां बिल्कुल। लेकिन पहले, क्या आप ऊपर बताए गए दूसरे गिस्ट पर एक नज़र डालना चाहेंगे? मैंने इस Gist पर दो फाइलें डालीं: एक स्क्रिप्ट द्वारा उपयोग की गई फ़ाइल है और दूसरी एक, वह स्क्रिप्ट ही है, जो फ़ाइल को पढ़ने के लिए "खुलने वाली" बाइनरी का उपयोग करती है और फिर, उस फ़ाइल का निर्माण करती है जिसमें SSL प्रमाणपत्र ( .crt)। मुझे पता है अगर आप पूरी बात को समझने में कामयाब रहे। सादर :)।
ivanleoncz

हम्म हाँ, मैंने उन 2 gists को देखा है, लेकिन मैं वास्तव में समझ नहीं पा रहा हूं कि मैं उनका उपयोग कैसे करूं?
jlively

4

इस समस्या से बचने के लिए आप अपने KeyStore में अतिरिक्त प्रमाणपत्र कैसे जोड़ सकते हैं: HTTPS पर HttpClient का उपयोग करके सभी प्रमाणपत्रों पर भरोसा करना

यह आपके द्वारा पूछे जाने पर उपयोगकर्ता को संकेत नहीं देगा, लेकिन इससे यह संभावना कम हो जाएगी कि उपयोगकर्ता "विश्वसनीय सर्वर प्रमाणपत्र नहीं" त्रुटि में चलेगा।


सिर्फ परीक्षण के उद्देश्य के लिए, आप इस ट्रिक के साथ प्ले स्टोर में कोई ऐप प्रकाशित नहीं कर सकते क्योंकि इसे अस्वीकार कर दिया जाएगा
एरियल

3

एसएसएल सर्टिफिकेट बनाने का सबसे सरल तरीका

ओपन फ़ायरफ़ॉक्स (मुझे लगता है कि यह क्रोम के साथ भी संभव है, लेकिन एफएफ के साथ मेरे लिए यह आसान है)

स्व-हस्ताक्षरित एसएसएल प्रमाणपत्र के साथ अपनी विकास साइट पर जाएं।

प्रमाणपत्र पर क्लिक करें (साइट के नाम के आगे)

"अधिक जानकारी" पर क्लिक करें

"देखें प्रमाण पत्र" पर क्लिक करें

"विवरण" पर क्लिक करें

"निर्यात ..." पर क्लिक करें

"X.509 सर्टिफिकेट व्हिथ चेन (PEM)" चुनें, इसे बचाने के लिए फ़ोल्डर और नाम का चयन करें और "सहेजें" पर क्लिक करें

कमांड लाइन पर जाएं, उस निर्देशिका पर जाएं जहां आपने pem फ़ाइल डाउनलोड की है और "Opensl x509 -inform PEM -outform DM -in .pem -out .crt" को निष्पादित करता है।

अपने एंड्रॉइड डिवाइस के अंदर / sdcard फ़ोल्डर की जड़ में .crt फ़ाइल को अपने एंड्रॉइड डिवाइस के अंदर कॉपी करें, सेटिंग्स> सुरक्षा> स्टोरेज से इंस्टॉल करें।

यह प्रमाण पत्र का पता लगाना चाहिए और आपको इसे डिवाइस में जोड़ने के लिए अपनी विकास साइट पर ब्राउज़ करें।

पहली बार इसे आपको सुरक्षा अपवाद की पुष्टि करने के लिए कहना चाहिए। बस इतना ही।

प्रमाणपत्र आपके एंड्रॉइड (ब्राउज़र, क्रोम, ओपेरा, डॉल्फिन ...) पर स्थापित किसी भी ब्राउज़र के साथ काम करना चाहिए

याद रखें कि यदि आप किसी भिन्न डोमेन से अपनी स्थैतिक फ़ाइलों की सेवा कर रहे हैं (हम सभी पृष्ठ गति की कुतिया हैं) तो आपको उस डोमेन के लिए प्रमाणपत्र भी जोड़ना होगा।


2

मैंने एंड्रॉइड पर विशेष प्रमाण पत्र पर भरोसा करने के लिए छोटे पुस्तकालय ssl-utils-android लिखा ।

आप संपत्ति निर्देशिका से फ़ाइल नाम देकर किसी भी प्रमाण पत्र को लोड कर सकते हैं।

उपयोग:

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

1

इन सुधारों में से किसी ने भी मेरे विकसित मंच को एसडीके 16, 4.1.1 रिलीज़ को लक्षित करने के लिए काम नहीं किया, इसलिए मुझे वर्कअराउंड मिला।

मेरा ऐप " 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 " पर प्रकाशित

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

जनवरी 19, 2020 स्व हस्ताक्षरित प्रमाणपत्र ISSUE FIX:

किसी भी स्व-हस्ताक्षरित प्रमाणपत्र के लिए वीडियो, छवि, कॉलिंग webservice खेलने के लिए या किसी भी असुरक्षित 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

शायद यह उपयोगी होगा ... यह स्व-हस्ताक्षरित प्रमाण पत्र का उपयोग करके जावा क्लाइंट पर काम करता है (प्रमाण पत्र की कोई जांच नहीं है)। सावधान रहें और इसका उपयोग केवल विकास के मामलों के लिए करें क्योंकि यह बिल्कुल भी सुरक्षित नहीं है !!

Apache HttpClient 4.0 में SSL प्रमाणपत्र त्रुटियों को कैसे अनदेखा करें

आशा है कि यह सिर्फ HttpClient लाइब्रेरी को जोड़ने के लिए एंड्रॉइड पर काम करेगा ... शुभकामनाएं !!


1
नहीं, यह एंड्रॉइड पर काम नहीं करता है क्योंकि यह एंड्रॉइड वैरिएंट में मौजूद नहीं है कि
डिप्रेक्टेड

0

यह SNI (सर्वर नाम पहचान) समर्थन inA, ndroid 2.x की कमी के परिणामस्वरूप होने वाली समस्या है। मैं एक सप्ताह तक इस समस्या से जूझ रहा था, जब तक कि मैं निम्नलिखित प्रश्न पर नहीं आया, जो न केवल समस्या की एक अच्छी पृष्ठभूमि देता है, बल्कि किसी भी सुरक्षा छेद से रहित और प्रभावी समाधान प्रदान करता है।

Android 2.3 में 'कोई सहकर्मी प्रमाणपत्र' त्रुटि नहीं है, लेकिन 4 में नहीं है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.