Glide Module Example: Accepting Self-Signed HTTPS Certificates

In our last Glide tutorial, you've learned the basics of GlideModules. They provide an easy access to some fundamental functions of Glide's core. You can quickly modify Glide's behavior by implementing and declaring GlideModules. Last week, we've changed the image quality to a higher decode format by utilizing the applyOptions() method. This week, we'll use the other method, registerComponents(), to modify Glide's network stack to accept connections and images from self-signed HTTPS servers.

Glide Series Overview

Modifying Glide With GlideModule

Before continuing to read, please make sure you read and understood our previous tutorials on GlideModules. We won't go over the basics in this tutorial again. Instead, we jump right to the issue. So make sure you're up-to-date with the fundamentals of GlideModules.

You're aware that GlideModules offer you two methods to change the behavior. Last week, we've looked at the first method, applyOptions(). This week, we'll use the other method, registerComponents(), to set a different network stack. By default, Glide internally uses a customized version of the standard HTTPUrlConnection to download images. Glide also offers integration libraries. All three of them are very strict in their security settings, which is very good. The only downside can be the situation when your images are on a server, which uses HTTPS, but uses a self-signed certificate. Glide would not load or display the images, since the self-signed certificates are considered a security issue.

Unsafe OkHttpClient

Thus, you'll need to implement your own network stack, which accepts self-signed certificates. Luckily, we've implemented and used an "unsafe" OkHttpClient before. We can just copy and paste the class, since it gives us a regular OkHttpClient, which we'll need to integrate:

public class UnsafeOkHttpClient {  
    public 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);
        }
    }
}

The created OkHttpClient disables all SSL certificate checks.

Integration into Glide

Our advantage is that the OkHttp integration library for Glide does almost the same thing, so we can follow their lead. First, we'll need to declare our customization in the GlideModule. As you already expected, we'll need to do the adaption in the registerComponents() method. We can call the .register() method to exchange some fundamental components of Glide. Glide uses a ModelLoader to link a data model to a concrete data type. In our example, we'll need to create a ModelLoader, which links an incoming URL, represented by the GlideUrl class to an InputStream. Glide needs to be able to create instances of our new ModelLoader, so we're passing a factory in the .register() method:

Glide 4.x

@GlideModule
public class UnsafeOkHttpGlideModule extends LibraryGlideModule {  
    @Override
    public void registerComponents(Context context, Glide glide, Registry registry) {
        OkHttpClient client = UnsafeOkHttpClient.getUnsafeOkHttpClient();
        registry.replace(GlideUrl.class, InputStream.class,
                new OkHttpUrlLoader.Factory(client));
    }
}

Glide 3.x

public class UnsafeOkHttpGlideModule implements GlideModule {  
        @Override
        public void applyOptions(Context context, GlideBuilder builder) {

        }

        @Override
        public void registerComponents(Context context, Glide glide) {
            OkHttpClient client = UnsafeOkHttpClient.getUnsafeOkHttpClient();
            glide.register(GlideUrl.class, InputStream.class,
                new OkHttpUrlLoader.Factory(client));
        }
    }

The first two parameters of the method are the model class and the linked resource class. The last parameter is the ModelLoaderFactory. Consequently, we can't set an UnsafeOkHttpClient instance directly, we'll need to pass a ModelLoaderFactory, which provides the link between the URL and the input stream using the UnsafeOkHttpClient. In this case we'll just re-use Glide's OkHttpUrlLoader class and pass our custom OkHttpClient object to the constructor.

Glide 3.x: Declaration of Glide Module

Finally, if you're using Glide 3.x, you need to declare the new module in the AndroidManifest.xml:

<manifest

    ...

    <application>

        <meta-data
            android:name="io.futurestud.tutorials.glide.glidemodule.UnsafeOkHttpClient"
            android:value="GlideModule" />

        ...

    </application>
</manifest>  

Outlook

In this tutorial, you've seen a different use case of changing the way Glide works. We've implemented an "unsafe" network stack and integrated it into Glide with the registerComponents() method of a GlideModule. But that's just the tip of the iceberg of possible Glide modifications.

Next week, we'll look at another option for a GlideModule to change Glide's caching behavior.

Explore the Library

Find interesting tutorials and solutions for your problems.