滑动 - javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: 找不到证书路径的信任锚点

19

我将服务器从HTTP迁移到HTTPS,我使用自签名证书发送网络请求,并且它可以工作,但是对于使用Glide加载图片而言无法工作。

在通过Glide库加载图片时,如果从https URL加载图片,则会出现javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found错误。

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

我尝试使用这个链接并使用了GlideModule,但似乎没有起作用,请帮忙。


这不是重复的问题,因为它与HTTPUrlConnection无关,我在使用Glide图像加载时遇到了这个问题。你能帮我解决吗? - Lalit Sharma
这是一个重复问题,因为问题完全相同:服务器证书不受信任。 - user207421
1
我们正在讨论仅在Glide上允许SSL证书的问题,并且该问题提供了Retrofit中相同问题的解决方案。 - Lalit Sharma
6个回答

12

这个问题涉及证书,请参考此链接 - https://stackoverflow.com/a/39032433/4741746

这将绕过证书,允许您进入系统。

请参阅此链接 - https://futurestud.io/tutorials/glide-module-example-accepting-self-signed-https-certificates

创建自定义GlideModule类,OkHttpUrlLoader类,并按照上述链接中提到的方式附加到Glide中。

您必须放置

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

在AndroidMainifest文件的应用程序标签内https://github.com/fs-opensource/android-tutorials-glide/blob/master/app/src/main/AndroidManifest.xml


请问这个会如何在现有的代码中运作?并且这个也能在生产环境中运行吗? - Lalit Sharma
2
最终,https://futurestud.io/tutorials/glide-module-example-accepting-self-signed-https-certificates 帮了大忙。感谢您的支持。 - Lalit Sharma
1
不安全的临时措施并不是答案,尤其是当它没有透露出不安全性时。 - user207421

5

你可以使用我从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>

谢谢,我刚刚添加了以下内容:1. "UnsafeOkHttpClient.java" 2.MyGlideModule.java 3.app/build.gradle 4.AndroidManifest.xml元数据,并且它正在工作。 - Avinash Shinde
这是很多设置啊哈哈。但说实话,你的解决方案非常完美。我真的很感激你的时间。 - Muhammad Farhan

2

我尝试使用Glide 4.x在imagview中加载https图像URL。我已经在我的代码中应用了各种开发人员的答案,但我没有成功加载图像。最后,我找到了一种解决方案,可以使用Glide加载https图像URL。为此,您必须按照以下步骤将证书附加到Glide请求。

步骤1:您需要从Glide官方 GitHub文档导入最新的Glide库。如果启用了proguard,则根据Glide文档中的说明在proguard文件中添加代码。

对于Java开发者

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'
               }

             }

针对Kotlin开发者

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'
               }

             }

步骤2:一旦Glide库成功地与您的项目构建在一起,就可以使用UnsafeOkHttpClient类。我已经在Java中创建了这个类,但您可以根据需要在Kotlin中创建它。

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

步骤3:现在开始创建一个类,该类扩展了AppGlideModule@GlideModule注释到该类。 注释后重新构建您的项目,它将在您的项目中创建一个GlideApp类。此类可帮助我们在glide尝试加载https url时发送SSL请求。

对于Java开发人员

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

 }

针对Kotlin开发者

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

步骤 4:使用 GlideApp,例如 GlideApp.with(this).load(imgUrl).into(glide_test_iv1)

摘要:Glide 4.0 不需要在 AndroidManifest.xml 中声明 "GlideModule"。您只需要按照以下步骤:

  1. YourAppGlideModule 扩展 AppGlideModule,您可以在 YourAppGlideModule 类中重写 applyOptions 函数。

  2. 您应该在 "android studio -> build -> make project" 中构建项目,它将生成 GlideApp 类。

  3. 使用 GlideApp,例如 GlideApp.with(this).load(imgUrl).into(glide_test_iv1)


2
以上两个答案都是正确的,但请注意以下依赖关系: 添加或更改 okhttp3-integration:4.4.0 版本。
  implementation ('com.github.bumptech.glide:okhttp3-integration:4.4.0'){
        exclude group: 'glide-parent'
    }

这个要写在哪里?我有implementation 'com.github.bumptech.glide:glide:4.11.0' - CoolMind
在应用程序文件夹的 build.gradle 文件中的依赖项部分。 - Rajesh N

1
我也遇到了这个问题。我使用了这个链接,并在应用程序的build.gradle中的plugins中添加了'kotlin-kapt',所以我的依赖关系是:
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"

我使用的代码是:
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);
    }
}

}

并且:

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

我将这个元数据添加到清单中:

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

我希望这对你有帮助。


-1

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

6
你能否进一步解释你的答案? - Shajeel Afzal
14
我不明白为什么人们投票支持这种不完整的答案! UnsafeHttpsClient.getUnsafeOkHttpClient(); 整个类都没有出现在解决方案中,完全没有任何解释,你只是简单地复制粘贴了代码。 - Sim
2
无法解决OkHttpUrlLoader => https://dev59.com/xVoU5IYBdhLWcg3wsYXM - IulianT
5
这个回答并没有解决任何问题!我很惊讶人们怎么会点赞它!这个解决方案中缺少一个完整的自定义类名为 UnsafeHttpsClient - sud007
1
https://medium.com/@starryzoo/glide-https-ssl-handshake-exception-e0f22b8457f1 - Abeer Iqbal
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接