Glide - javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found
Asked Answered
D

6

19

I migrated the server from HTTP to HTTPS I have used self-signed certificate to send network requests with HttpUrlConnection and it worked but for image loading it is not working as I have used Glide for Image loading.

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.while loading images from https URL through glide library

Glide.with(mContext).load(currentItem.getImage_path().replace(" ", "%20"))
     .listener(new RequestListener<String, GlideDrawable>() {
        @Override
        public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
            genericViewHolder.imageView_1.setImageResource(R.drawable.image_thumbnail);
            genericViewHolder.progressBar.setVisibility(View.GONE);
            return false;
        }

        @Override
        public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
            genericViewHolder.progressBar.setVisibility(View.GONE);
            return false;
        }
    }).into(genericViewHolder.imageView_1);

I tried using this link and used GlideModule but it does not seem to work. Please help.

Dreddy answered 13/12, 2016 at 6:0 Comment(4)
Possible duplicate of javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not foundLazaretto
It's not duplicate because it does not belong to HTTPUrlConnection, I facing this issue with Glide image loading. Can you help me out pls?Dreddy
It is a duplicate because the issue is exactly the same: the server certificate isn't trusted.Lazaretto
We are discussing here to allow SSL certificate on Glide only and that question provides resolution of the same issue in Retrofit.Dreddy
A
12

The issue is about certificate follow this link -https://mcmap.net/q/35918/-javax-net-ssl-sslhandshakeexception-java-security-cert-certpathvalidatorexception-trust-anchor-for-certification-path-not-found

This will bypass certificate and allow you to enter in system

see this link also -https://futurestud.io/tutorials/glide-module-example-accepting-self-signed-https-certificates

Create your custom GlideModule Class,OkHttpUrlLoader class and attach to you Glide as mention in above link

You have to put

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

Inside application tag of your AndroidMainifiest file https://github.com/fs-opensource/android-tutorials-glide/blob/master/app/src/main/AndroidManifest.xml

Allometry answered 13/12, 2016 at 6:23 Comment(3)
Could you please tell me how this will work with existing code? And will this work in production too?Dreddy
finally, the futurestud.io/tutorials/… helped. Thanks for the supportDreddy
An insecure bandaid is not an answer, especially when it doesn't disclose the insecurity.Lazaretto
H
5

You can use this code that I copied from the answer at Trusting all certificates with okHttp

Create class UnsafeOkHttpClient.java

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);
    }
}
}

Create a class MyGlideModule.java

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

Create a class OkHttpStreamFetcher.java

public class OkHttpStreamFetcher implements DataFetcher<InputStream>, okhttp3.Callback {
private static final String TAG = "OkHttpFetcher";
private final Call.Factory client;
private final GlideUrl url;
private InputStream stream;
private ResponseBody responseBody;
private DataCallback<? super InputStream> callback;
private volatile Call call;

// Public API.
@SuppressWarnings("WeakerAccess")
public OkHttpStreamFetcher(Call.Factory client, GlideUrl url) {
    this.client = client;
    this.url = url;
}

@Override
public void loadData(
        @NonNull Priority priority, @NonNull final DataCallback<? super InputStream> callback) {
    Request.Builder requestBuilder = new Request.Builder().url(url.toStringUrl());
    for (Map.Entry<String, String> headerEntry : url.getHeaders().entrySet()) {
        String key = headerEntry.getKey();
        requestBuilder.addHeader(key, headerEntry.getValue());
    }
    Request request = requestBuilder.build();
    this.callback = callback;

    call = client.newCall(request);
    call.enqueue(this);
}

@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
    if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "OkHttp failed to obtain result", e);
    }

    callback.onLoadFailed(e);
}

@Override
public void onResponse(@NonNull Call call, @NonNull Response response) {
    responseBody = response.body();
    if (response.isSuccessful()) {
        long contentLength = Preconditions.checkNotNull(responseBody).contentLength();
        stream = ContentLengthInputStream.obtain(responseBody.byteStream(),

contentLength); callback.onDataReady(stream); } else { callback.onLoadFailed(new HttpException(response.message(), response.code())); } }

@Override
public void cleanup() {
    try {
        if (stream != null) {
            stream.close();
        }
    } catch (IOException e) {
        // Ignored
    }
    if (responseBody != null) {
        responseBody.close();
    }
    callback = null;
}

@Override
public void cancel() {
    Call local = call;
    if (local != null) {
        local.cancel();
    }
}

@NonNull
@Override
public Class<InputStream> getDataClass() {
    return InputStream.class;
}

@NonNull
@Override
public DataSource getDataSource() {
    return DataSource.REMOTE;
}
}

Create a class OkHttpUrlLoader.java

public class OkHttpUrlLoader implements ModelLoader<GlideUrl, InputStream> {

private final Call.Factory client;

// Public API.
@SuppressWarnings("WeakerAccess")
public OkHttpUrlLoader(@NonNull Call.Factory client) {
    this.client = client;
}

@Override
public boolean handles(@NonNull GlideUrl url) {
    return true;
}

@Override
public LoadData<InputStream> buildLoadData(
        @NonNull GlideUrl model, int width, int height, @NonNull Options options) {
    return new LoadData<>(model, new OkHttpStreamFetcher(client, model));
}

public static class Factory implements ModelLoaderFactory<GlideUrl, InputStream> {
    private static volatile Call.Factory internalClient;
    private final Call.Factory client;

    private static Call.Factory getInternalClient() {
        if (internalClient == null) {
            synchronized (Factory.class) {
                if (internalClient == null) {
                    internalClient = new OkHttpClient();
                }
            }
        }
        return internalClient;
    }

    public Factory() {
        this(getInternalClient());
    }

    public Factory(@NonNull Call.Factory client) {
        this.client = client;
    }

    @NonNull
    @Override
    public ModelLoader<GlideUrl, InputStream> build(MultiModelLoaderFactory multiFactory) {
        return new OkHttpUrlLoader(client);
    }

    @Override
    public void teardown() {
        // Do nothing, this instance doesn't own the client.
    }
}
}

Add app/build.gradle

implementation 'com.github.bumptech.glide:glide:4.10.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'
implementation("com.github.bumptech.glide:okhttp3-integration:4.2.0")

{ exclude group: 'glide-parent' }

In AndroidManifest.xml

<application>
<meta-data
        android:name="Replace_your_package_name.UnsafeOkHttpClient"
        android:value="MyGlideModule" />
</application>
Housetop answered 4/9, 2020 at 11:30 Comment(2)
Thanks for that I just added 1. "UnsafeOkHttpClient.java" 2.MyGlideModule.java 3.app/build.gradle 4. AndroidManifest.xml meta data and its working.Evvy
That's a lot of setups hahah. But to be honest your solution is perfect. I really appreciate your time.Pyrophoric
S
2

Above both answer right but make sure also below dependency Add or change okhttp3-integration:4.4.0 version

  implementation ('com.github.bumptech.glide:okhttp3-integration:4.4.0'){
        exclude group: 'glide-parent'
    }
Splendor answered 7/9, 2019 at 13:8 Comment(2)
Where to write this? I have implementation 'com.github.bumptech.glide:glide:4.11.0'.Prevocalic
in app folder's build.gradle file in dependency sectionSplendor
M
2

I have try to load https Image URL inside imagview using Glide 4.x. I have apply various developer answer inside my code but I didn't get success to load images. Finally I found a solution to load https image URL inside imageview using Glide. For that you have to follow below steps to attach certificate with glide request.

Step 1: You to import Latest glide library from glide official GitHub documentation. If you enable proguard then add code inside proguard file as per mention in glide documentation.

For Java developer

dependencies { 

               implementation 'com.github.bumptech.glide:glide:4.11.0' 
               annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
               implementation("com.github.bumptech.glide:okhttp3-integration:4.11.0") {
                     exclude group: 'glide-parent'
               }

             }

For Kotling developer

dependencies { 

               implementation 'com.github.bumptech.glide:glide:4.11.0' 
               kapt 'com.github.bumptech.glide:compiler:4.11.0'
               implementation("com.github.bumptech.glide:okhttp3-integration:4.11.0") {
                        exclude group: 'glide-parent'
               }

             }

Step 2: Once Glide Library successfully build with your project. UnsafeOkHttpClient clas. I have created this class in java but you can create this in kotlin as per your need.

public class OkHttpStreamFetcher implements DataFetcher<InputStream>, okhttp3.Callback {
private static final String TAG = "OkHttpFetcher";
private final Call.Factory client;
private final GlideUrl url;
private InputStream stream;
private ResponseBody responseBody;
private DataFetcher.DataCallback<? super InputStream> callback;
private volatile Call call;

// Public API.
@SuppressWarnings("WeakerAccess")
public OkHttpStreamFetcher(Call.Factory client, GlideUrl url) {
    this.client = client;
    this.url = url;
}

@Override
public void loadData(
        @NonNull Priority priority, @NonNull final DataCallback<? super InputStream> callback) {
    Request.Builder requestBuilder = new Request.Builder().url(url.toStringUrl());
    for (Map.Entry<String, String> headerEntry : url.getHeaders().entrySet()) {
        String key = headerEntry.getKey();
        requestBuilder.addHeader(key, headerEntry.getValue());
    }
    Request request = requestBuilder.build();
    this.callback = callback;

    call = client.newCall(request);
    call.enqueue(this);
}

@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
    if (Log.isLoggable(TAG, Log.DEBUG)) {
        Log.d(TAG, "OkHttp failed to obtain result", e);
    }

    callback.onLoadFailed(e);
}

@Override
public void onResponse(@NonNull Call call, @NonNull Response response) {
    responseBody = response.body();
    if (response.isSuccessful()) {
        long contentLength = Preconditions.checkNotNull(responseBody).contentLength();
        stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength);
        callback.onDataReady(stream);
    } else {
        callback.onLoadFailed(new HttpException(response.message(), response.code()));
    }
}

@Override
public void cleanup() {
    try {
        if (stream != null) {
            stream.close();
        }
    } catch (IOException e) {
        // Ignored
    }
    if (responseBody != null) {
        responseBody.close();
    }
    callback = null;
}

@Override
public void cancel() {
    Call local = call;
    if (local != null) {
        local.cancel();
    }
}

@NonNull
@Override
public Class<InputStream> getDataClass() {
    return InputStream.class;
}

@NonNull
@Override
public DataSource getDataSource() {
    return DataSource.REMOTE;
}  }

Step 3: Now Start create on class which extends with AppGlideModule and @GlideModule annotation to that class. After annotation Rebuild your project and it will create one class GlideApp class inside your project. This class help us to send SSL request when glide try to load https url.

For Java Developer

@GlideModule
public class MyAppGlideModule extends AppGlideModule {

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

 }

For Kotlin Devloper

@GlideModule
class AppGlideModule : AppGlideModule(){
           override fun registerComponents(@NonNull context: Context, @NonNull glide: Glide, @NonNull registry: Registry) {
                      val okHttpClient = UnsafeOkHttpClient.getUnsafeOkHttpClient()
                      registry.replace(GlideUrl::class.java, InputStream::class.java, OkHttpUrlLoader.Factory(okHttpClient))
            }
 }

Step 4: Use the GlideApp such as GlideApp.with(this).load(imgUrl).into(glide_test_iv1)

Summary: Glide 4.0 need not have declare "GlideModule" in AndroidManifest.xml. You just need to following steps:

  1. YourAppGlideModule extends AppGlideModule, you can override function applyOptions in the YourAppGlideModule class.

  2. You should make project in "android studio -> build -> make project", it will generate the GlideApp class.

  3. Use the GlideApp such as GlideApp.with(this).load(imgUrl).into(glide_test_iv1)

Mitzvah answered 27/12, 2020 at 16:13 Comment(0)
B
2

I had this problem too. I used this link and I add 'kotlin-kapt' to plugins in build.gradle of the app so my dependencies was:

def glide_version = '4.15.1'
implementation "com.github.bumptech.glide:glide:$glide_version"
implementation "com.github.bumptech.glide:annotations:$glide_version"
implementation "com.github.bumptech.glide:okhttp3-integration:$glide_version"
kapt "com.github.bumptech.glide:compiler:$glide_version"

the code i used was:

public class UnsafeOkHttpClient {

public static OkHttpClient getUnsafeOkHttpClient() {
    try {
        @SuppressLint("CustomX509TrustManager") final TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    @SuppressLint("TrustAllX509TrustManager")
                    @Override
                    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                    }


                    @SuppressLint("TrustAllX509TrustManager")
                    @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("TLSv1.2");
        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()
                .connectTimeout(20, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true);

        builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
        builder.hostnameVerifier((hostname, session) -> true);


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

}

and:

@GlideModule
class MyGlideAppModule : AppGlideModule() {
    override fun registerComponents(context: Context, glide: Glide, registry: Registry) {

        val client = UnsafeOkHttpClient.getUnsafeOkHttpClient()

        val factory: OkHttpUrlLoader.Factory = OkHttpUrlLoader.Factory(client)

        registry.replace(
            GlideUrl::class.java,
            InputStream::class.java, factory
        )
    }
}

and I add this meta-data to manifest:

<meta-data android:name="${applicationId}.network.MyGlideAppModule" android:value="AppGlideModule" />

I hode this be helpfull.

Bequeath answered 27/6, 2023 at 21:26 Comment(0)
U
-1

For Glide 4

@GlideModule
public class MyGlideModule extends AppGlideModule {

    @Override
    public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {

        //To Attach Self Signed Ssl Certificate
        /*OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .sslSocketFactory(sslSocketFactory, X509TrustManager)
                .build();*/

        //Unsafe Okhttp client
        OkHttpClient okHttpClient= UnsafeHttpsClient.getUnsafeOkHttpClient();

        registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(okHttpClient));
    }
}
Unnatural answered 24/2, 2018 at 19:16 Comment(8)
Can you please explain your answer a little bit further?Crag
i don't get why people voted this kind of incomplete answer ! UnsafeHttpsClient.getUnsafeOkHttpClient(); the whole class is missing from the solution there is no explanation at all, you just copy pasted your code that's it .Chloro
unable to resolve OkHttpUrlLoader => #37208543Alkoran
This answer does not resolve to anything! I am surprised how people have upvoted this! A complete custom class named UnsafeHttpsClient is missing from the solution.Smother
Incomplete answer -1Vicennial
medium.com/@starryzoo/…Ramshackle
I wrote a similar solution as many other people did: https://mcmap.net/q/35851/-trust-anchor-not-found-for-android-ssl-connection.Prevocalic
You Need to add these following classes 1. "UnsafeOkHttpClient.java" 2.MyGlideModule.java 3.app/build.gradle 4. AndroidManifest.xml meta data. Answer is already present on this page.Evvy

© 2022 - 2024 — McMap. All rights reserved.