一.获取证书
假设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注解即可,不需要手动调用