OkHttp সহ সমস্ত শংসাপত্রের উপর বিশ্বাস রাখা


111

পরীক্ষার উদ্দেশ্যে, আমি আমার ওকে এইচটিটিপি ক্লায়েন্টে একটি সকেট কারখানা যুক্ত করার চেষ্টা করছি যা প্রক্সি সেট হওয়ার সময় সমস্ত কিছুতে বিশ্বাস করে। এটি বহুবার হয়েছে, তবে আমার একটি বিশ্বাসযোগ্য সকেট কারখানার বাস্তবায়নটি কিছু অনুপস্থিত বলে মনে হচ্ছে:

class TrustEveryoneManager implements X509TrustManager {
    @Override
    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { }

    @Override
    public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { }

    @Override
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}
OkHttpClient client = new OkHttpClient();

final InetAddress ipAddress = InetAddress.getByName("XX.XXX.XXX.XXX"); // some IP
client.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ipAddress, 8888)));

SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManager[] trustManagers = new TrustManager[]{new TrustEveryoneManager()};
sslContext.init(null, trustManagers, null);
client.setSslSocketFactory(sslContext.getSocketFactory);

আমার অ্যাপ্লিকেশন থেকে কোনও অনুরোধ প্রেরণ করা হচ্ছে না এবং কোনও ব্যতিক্রম লগ করা হচ্ছে না বলে মনে হচ্ছে এটি ওকে এইচটিটিপি-র মধ্যে নিঃশব্দে ব্যর্থ হচ্ছে। আরও তদন্ত করার পরে, মনে Connection.upgradeToTls()হয় হ্যান্ডশেক জোর করা হচ্ছে যখন OkHttp এর একটি ব্যতিক্রম গ্রাস করা আছে । আমাকে যে ব্যতিক্রম দেওয়া হচ্ছে তা হ'ল:javax.net.ssl.SSLException: SSL handshake terminated: ssl=0x74b522b0: SSL_ERROR_ZERO_RETURN occurred. You should never see this.

নিম্নলিখিত কোডটি SSLContextএমন একটি উত্পাদন করে যা কোনও এসএসএলসকেট ফ্যাক্টরি তৈরি করতে মনোযোগের মতো কাজ করে যা কোনও ব্যতিক্রম ছুঁড়ে না:

protected SSLContext getTrustingSslContext() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
    final SSLContextBuilder trustingSSLContextBuilder = SSLContexts.custom()
            .loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true; // Accepts any ssl cert whether valid or not.
                }
            });
    return trustingSSLContextBuilder.build();
}

সমস্যাটি হ'ল আমি আমার অ্যাপ্লিকেশন থেকে সমস্ত অ্যাপাচি এইচটিপিপিপ্লায়েন্ট নির্ভরতা পুরোপুরি সরিয়ে দেওয়ার চেষ্টা করছি। অ্যাপাচি এইচটিপিপ্লিনেন্টের সাথে অন্তর্নিহিত কোডটি SSLContextযথেষ্ট সরল মনে হচ্ছে, তবে আমি স্পষ্টতই কিছু অনুভব করছি কারণ আমি এটির সাথে SSLContextমেলে কনফিগার করতে পারি না ।

কেউ কি এসএসএল কনটেক্সট বাস্তবায়ন তৈরি করতে সক্ষম হবেন যা অ্যাপাচি এইচটিপিপিলেট ব্যবহার না করে আমি যা চাই তা করতে পারে?


2
"পরীক্ষার উদ্দেশ্যে, আমি আমার ওকে এইচটিএইচপি ক্লায়েন্টে একটি সকেট কারখানা যুক্ত করার চেষ্টা করছি যা সবকিছুর উপর নির্ভর করে" - আপনি কী ভাবেন যে এটি প্রথম স্থানে একটি ভাল ধারণা?
CommonsWare

1
এটি কেবলমাত্র সম্পূর্ণরূপে নির্ভর করে এমন কোনও নেটওয়ার্কে কল করা হয়।
সিটো

এর কারণ হিসাবে একটি হয়java.net.SocketTimeoutException: Read timed out
ইগোরগানাপলস্কি

উত্তর:


249

এখানে যদি কেউ পড়ে যায় তবে আমার জন্য কাজ করা (একমাত্র) সমাধানটি এখানে বর্ণিত OkHttpClientমত তৈরি করছে ।

কোডটি এখানে:

private static OkHttpClient getUnsafeOkHttpClient() {
  try {
    // Create a trust manager that does not validate certificate chains
    final TrustManager[] trustAllCerts = new TrustManager[] {
        new X509TrustManager() {
          @Override
          public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
          }

          @Override
          public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
          }

          @Override
          public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[]{};
          }
        }
    };

    // Install the all-trusting trust manager
    final SSLContext sslContext = SSLContext.getInstance("SSL");
    sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
    // Create an ssl socket factory with our all-trusting manager
    final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

    OkHttpClient.Builder builder = new OkHttpClient.Builder();
    builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]);
    builder.hostnameVerifier(new HostnameVerifier() {
      @Override
      public boolean verify(String hostname, SSLSession session) {
        return true;
      }
    });

    OkHttpClient okHttpClient = builder.build();
    return okHttpClient;
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
}

15
কেন SSLএবং না TLS?
ইগোরগানাপলস্কি

1
এটার জন্য অনেক ধন্যবাদ! Retrofit (ওখট্টিপি ব্যবহার করে) এর ডকুমেন্টেশনের অভাব রয়েছে, এই জাতীয় কোডের নমুনাগুলি বার বার আমার অনেক সময় সাশ্রয় করে।
ওয়ারপজিট

8
নোট করুন যে এই পদ্ধতিটি OkHttp এর বর্তমান সংস্করণগুলির সাথে আর কাজ করে না। 3.1.1 দিয়ে এটি সম্পূর্ণরূপে ভাঙ্গা মনে হচ্ছে। ৩.১.২ থেকে পরবর্তী স্থানে X509TrustManager.getAcceptedIssuers()অবশ্যই একটি খালি অ্যারে ফিরতে হবে null। আরও তথ্যের জন্য, এই প্রতিশ্রুতিটি দেখুন (নিচে স্ক্রোল করুন এবং রিয়েলট্রাস্টআরটআইন্ডেক্স.জভাতে নোটগুলি দেখুন)।
জেবিএক্সবার্গদেব

12
আমি এটি চেষ্টা করেছি, তবে আমি এখনও এর Handshake failedব্যতিক্রম পাই । কোনও পরামর্শ?
এস্তেবান

1
OkHttpClient থেকে উদাহরণ: github.com/square/okhttp/blob/master/sample/guide/src/main/…
ilyamuromets

13

নিম্নলিখিত পদ্ধতি হ্রাস করা হয়

sslSocketFactory(SSLSocketFactory sslSocketFactory)

এটিকে আপডেট করার বিষয়ে বিবেচনা করুন

sslSocketFactory(SSLSocketFactory sslSocketFactory, X509TrustManager trustManager)

13

OkHttp 3.0 আপডেট করুন, getAcceptedIssuers()ফাংশনটির পরিবর্তে একটি খালি অ্যারে ফিরিয়ে দিতে হবে null


2
@ ওভাররাইড পাবলিক এক্স509 সার্টিফিকেট [] getAcceptedIssuers () new নতুন এক্স509 সার্টিফিকেট ফিরে আসুন [] St}; // স্ট্যাকওভারফ্লো}
এরভিন জাং

11

এসএসএলসকেটফ্যাক্টরির এটির এক্স 509 ট্রাস্টম্যানেজারটি প্রকাশ করে না, যা এমন ক্ষেত্র যা OkHttp একটি পরিষ্কার শংসাপত্র শৃঙ্খলা তৈরি করা দরকার। পরিবর্তে এই পদ্ধতিটি বিশ্বাস পরিচালককে নিষ্কাশন করতে প্রতিবিম্বটি ব্যবহার করতে হবে use অ্যাপ্লিকেশনগুলিতে এসএসএলসকেটফ্যাক্টরি (এসএসএলসকেটফ্যাক্টরি, এক্স 509 ট্রাস্টম্যানেজার) কল করতে পছন্দ করা উচিত, যা এ জাতীয় প্রতিচ্ছবি এড়িয়ে চলে।

উত্স: OkHttp ডকুমেন্টেশন

OkHttpClient.Builder builder = new OkHttpClient.Builder();

builder.sslSocketFactory(sslContext.getSocketFactory(),
    new X509TrustManager() {
        @Override
        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[]{};
        }
    });

এটি স্ব-স্বাক্ষরিত শংসাপত্রগুলির জন্য কাজ করে না। কারণ ক 401 অননুমোদিত ত্রুটি।
ইগোরগানাপলস্কি

5
কোথা sslContextথেকে আসে?
অনায়সেস

3
আপনি কীভাবে আরম্ভ করবেন sslContext?
কিলটেক

9

এটি কোটলিনে সোনসুরক্সোর সমাধান, যদি কারও এটির প্রয়োজন হয়।

private fun getUnsafeOkHttpClient(): OkHttpClient {
    // Create a trust manager that does not validate certificate chains
    val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
        override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {
        }

        override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
        }

        override fun getAcceptedIssuers() = arrayOf<X509Certificate>()
    })

    // Install the all-trusting trust manager
    val sslContext = SSLContext.getInstance("SSL")
    sslContext.init(null, trustAllCerts, java.security.SecureRandom())
    // Create an ssl socket factory with our all-trusting manager
    val sslSocketFactory = sslContext.socketFactory

    return OkHttpClient.Builder()
        .sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
        .hostnameVerifier { _, _ -> true }.build()
}

7

আমি কোটলিনের জন্য একটি এক্সটেনশন ফাংশন করেছি। আপনি যেখানে পছন্দ করেন সেখানে এটি আটকান এবং তৈরি করার সময় এটি আমদানি করুন OkHttpClient

fun OkHttpClient.Builder.ignoreAllSSLErrors(): OkHttpClient.Builder {
    val naiveTrustManager = object : X509TrustManager {
        override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
        override fun checkClientTrusted(certs: Array<X509Certificate>, authType: String) = Unit
        override fun checkServerTrusted(certs: Array<X509Certificate>, authType: String) = Unit
    }

    val insecureSocketFactory = SSLContext.getInstance("TLSv1.2").apply {
        val trustAllCerts = arrayOf<TrustManager>(naiveTrustManager)
        init(null, trustAllCerts, SecureRandom())
    }.socketFactory

    sslSocketFactory(insecureSocketFactory, naiveTrustManager)
    hostnameVerifier(HostnameVerifier { _, _ -> true })
    return this
}

এটি এর মতো ব্যবহার করুন:

val okHttpClient = OkHttpClient.Builder().apply {
    // ...
    if (BuildConfig.DEBUG) //if it is a debug build ignore ssl errors
        ignoreAllSSLErrors()
    //...
}.build()

আপনি প্রকৃতপক্ষে এটি এর মতো ব্যবহার করতে পারেন: OkHttpClient.Builder () .ignoreAllSSLErferences ()। কানেক্টটাইমআউট (api.Toutout, সময়উনিট.সেকেন্ডস) .writTimeout (api.Toutout, সময়উনিট.সেকেন্ডস) ইত্যাদি, এটি সর্বোপরি একটি বিল্ডার প্যাটার্ন
ইমানুয়েল মেকলিন

1

কারও যদি এটির প্রয়োজন হয় তবে এটি স্কেল সমাধান

def anUnsafeOkHttpClient(): OkHttpClient = {
val manager: TrustManager =
  new X509TrustManager() {
    override def checkClientTrusted(x509Certificates: Array[X509Certificate], s: String) = {}

    override def checkServerTrusted(x509Certificates: Array[X509Certificate], s: String) = {}

    override def getAcceptedIssuers = Seq.empty[X509Certificate].toArray
  }
val trustAllCertificates =  Seq(manager).toArray

val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, trustAllCertificates, new java.security.SecureRandom())
val sslSocketFactory = sslContext.getSocketFactory()
val okBuilder = new OkHttpClient.Builder()
okBuilder.sslSocketFactory(sslSocketFactory, trustAllCertificates(0).asInstanceOf[X509TrustManager])
okBuilder.hostnameVerifier(new NoopHostnameVerifier)
okBuilder.build()

}


-12

আপনার কোডটিতে শংসাপত্রের বৈধতা কখনই ওভাররাইড করা উচিত নয়! আপনার যদি পরীক্ষা করার দরকার হয় তবে একটি অভ্যন্তরীণ / পরীক্ষার সিএ ব্যবহার করুন এবং ডিভাইস বা এমুলেটরটিতে সিএ রুট শংসাপত্র ইনস্টল করুন। আপনি কীভাবে সিএ সেটআপ করবেন তা না জানলে আপনি বারপসুইট বা চার্লস প্রক্সি ব্যবহার করতে পারেন


37
উহু চলো. আপনি যদি কোনও সংস্থার হয়ে কাজ করছেন এবং তারা আপনাকে ভিপিএন এর মাধ্যমে তাদের এইচটিটিপিএস সার্ভারের সাথে সংযোগ করতে বাধ্য করছে তবে কী হবে। আপনি কিভাবে পরীক্ষাতে অনুকরণ করবেন?
ইগোরগানাপলস্কি

5
ইয়া হ'ল শুদ্ধতম হগ-ওয়াশ। আমরা কেবল পরীক্ষার বিল্ডগুলিতে এটি সংকলন করি, তাই কোনও বিপদ নেই।
আদম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.