Android添加Https自签名证书(Retrofit 2.x、OkHttp 3.x、Glide 4.x)

一.获取证书

假设app要请求的网址是https://192.168.1.6:8080,在Chrome浏览器中输入网址
在这里插入图片描述
会显示证书不安全
从浏览器中到处证书
在这里插入图片描述
点击证书后出现如下窗口
在这里插入图片描述
点击复制文件,然后下一步到
在这里插入图片描述
选择好格式后点下一步,选择路径,后缀可以为.crt或.cer
在这里插入图片描述
后面就是下一步,然后完成
然后就可以在选择的导出路径处看到从浏览器中导出的https自签名证书
在这里插入图片描述

二.导入证书到项目中

将获取的证书放到app目录下的res/raw文件中
在这里插入图片描述

三.向OkHttp添加证书

在创建httpClient的地方将证书导入

private static Retrofit createRetrofit(String baseUrl){
    
    
        httpClient = new OkHttpClient.Builder()
                .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
                // 注释下面的代码,将关闭在每次 http 请求的时候输出日志
                .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
                .addInterceptor(chain -> {
    
    
                    Request request = chain.request();
                    if (userAgent != null) {
    
    
                        request = request.newBuilder()
                                .header(ApiConstant.Param.USER_AGENT, userAgent)
                                .header(ApiConstant.Param.LANG, config.getLang())
                                .header(ApiConstant.Param.AREA_CODE,config.getAreaCode())
                                .build();
                    }
                    return chain.proceed(request);
                })
                //
                .sslSocketFactory(sslSocketFactory, trustManager)//此处就是添加证书
                .build();
        Retrofit retrofit = new Retrofit.Builder()
                .client(httpClient)
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        return retrofit;
    }

对于sslSocketFactory, trustManager的赋值代码如下

static X509TrustManager trustManager;
    static SSLSocketFactory sslSocketFactory;

    public static void setCer(InputStream cerIn){
    
    
        //读取自签名证书
        try {
    
    
            //通过trustManagerForCertificates方法为证书生成 TrustManager
            trustManager = trustManagerForCertificates(cerIn);
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, new TrustManager[]{
    
    trustManager}, null);
            sslSocketFactory = sslContext.getSocketFactory();
        } catch (GeneralSecurityException e) {
    
    
            throw new RuntimeException(e);
        }
    }

另外调用到的函数

private static KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
    
    
        try {
    
    
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            InputStream in = null;
            // 传入 'null' 会生成一个空的 Keytore
            //password 用于检查 KeyStore 完整性和 KeyStore 解锁
            keyStore.load(in, password);
            return keyStore;
        } catch (IOException e) {
    
    
            throw new AssertionError(e);
        }
    }
public static X509TrustManager trustManagerForCertificates(InputStream in) throws GeneralSecurityException {
    
    
        //InputStream 可以包含多个证书

        //CertificateFactory 用于生成 Certificate,也就是数字证书
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        //由输入流生成证书
        Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);
        if (certificates.isEmpty()) {
    
    
            throw new IllegalArgumentException("expected non-empty set of trusted certificates");
        }

        // 将证书放入 keyStore
        char[] password = "password".toCharArray(); // "password"可以任意设置
        KeyStore keyStore = newEmptyKeyStore(password);
        int index = 0;
        for (Certificate certificate : certificates) {
    
    
            String certificateAlias = Integer.toString(index++);
            keyStore.setCertificateEntry(certificateAlias, certificate);
        }

        // 用 KeyStore 生成 X509 trust manager.
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, password);
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
    
    
            throw new IllegalStateException("Unexpected default trust managers:"
                    + Arrays.toString(trustManagers));
        }
        return (X509TrustManager) trustManagers[0];
    }

最后在Application的onCreate函数中调用

setCer(getResources().openRawResource(R.raw.watt));

watt就是导出的https证书的文件名
另外给出import文件

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

四.给Glide设置https自签名证书

添加依赖,版本号与Glide版本号相同

implementation “com.github.bumptech.glide:okhttp3-integration:4.11.0”

新建一个OkHttpAppGlideModule类,继承AppGlideModule

import android.content.Context;
import androidx.annotation.NonNull;
import com.bumptech.glide.Glide;
import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.Registry;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.module.AppGlideModule;
import java.io.InputStream;

@GlideModule
public class OkHttpAppGlideModule extends AppGlideModule {
    
    

    @Override
    public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
    
    
        registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(RetrofitManager.getHttpClient()));
    }

    @Override
    public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
    
    }
}

RetrofitManager.getHttpClient()获取的是在第三步中创建的httpClient
只需要添加@GlideModule注解即可,不需要手动调用

猜你喜欢

转载自blog.csdn.net/qq_17282141/article/details/109536409