用Retrofit访问Https的解决办法:
第一步:下载jar包
jdk默认情况下是不支持BKS证书格式,需要额外下载jar包,具体步骤如下:
1、下载jar包,下载地址 https://www.bouncycastle.org/download/bcprov-ext-jdk15on-154.jar
2、将下载好的bcprov-ext-jdk15on-154.jar复制到%JDK_HOME%\jre\lib\ext下
3、用文本编辑器打开%JDK_HOME%\jre\lib\security\java.security文件,在相应位置添加如下配置(前面已经有10个了)
security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider
第二步:证书文件准备。
在相应平台上下载SSL证书(Tomcat),得到pfx格式证书,需要在windows上导入导出,以得到带有顶级根的pfx证书,操作如下:
1、双击安装pfx格式证书,输入密码后,其他按默认方式进行下一步操作(过程中需要选择 允许导出私钥),直到完成。
2、开始-->运行,输入certmgr.msc,在个人-->证书中找到刚刚安装的证书文件,右键该证书,选择所有任务-->导出。
导出的过程注意要勾选运行导出私钥,其他默认方式,密码设置要简单(6位数),如111111(否则后面转换BKS证书的时候会提示非法私钥),直到完成。
第三步:使用刚刚调整过的jdk环境,转换证书格式。
windows环境:
开始-->运行,输入cmd,通过cd命令,进入%JDK_HOME%\jre\bin目录下,输入如下命令
keytool -importkeystore -srckeystore path\name.pfx -destkeystore path\name.bks -srcstoretype PKCS12 -deststoretype BKS
path\name ---->(文件路径和文件名)
执行命令之后会要求输入三次密码,前两个密码是BKS证书文件密码(这里的密码可以任意设置),最后一个是新转换的PFX证书文件的密码。
Linux环境:
通过cd命令,进入到%JDK_HOME%/jre/bin目录下,输入如下命令
./keytool -importkeystore -srckeystore path/name.pfx -destkeystore path/name.bks -srcstoretype PKCS12 -deststoretype BKS
path\name ---->(文件路径和文件名)
执行命令之后会要求输入三次密码,前两个密码是bks证书文件密码,最后一个是新转换的pfx证书文件的密码。
第四步:验证BKS证书文件
keytool -list -v -storetype BKS -keystore path\name.bks
./keytool -list -v -storetype BKS -keystore path/name.bks
第五步:导入BKS证书
然后把生成的证书文件key放入项目目录的raw文件夹下(可任意新建路径,代码添加时写回对应的路径即可),没有raw的话就新建一个即可,这里key是bks后缀的。
1、新建SslContextFactory:
public class SslContextFactory {
private static final String CLIENT_TRUST_PASSWORD = "111111";//信任证书密码,"这里写入你自己设置的密码"
private static final String CLIENT_AGREEMENT = "TLS";//使用协议
private static final String CLIENT_TRUST_MANAGER = "X509";
private static final String CLIENT_TRUST_KEYSTORE = "BKS";
SSLContext sslContext = null;
public SSLContext getSslSocket(Context context) {
try {
//取得SSL的SSLContext实例
sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);
//取得TrustManagerFactory的X509密钥管理器实例
TrustManagerFactory trustManager = TrustManagerFactory.getInstance(CLIENT_TRUST_MANAGER);
//取得BKS密库实例
KeyStore tks = KeyStore.getInstance(CLIENT_TRUST_KEYSTORE);
InputStream is = context.getResources().openRawResource(R.raw.key);
try {
tks.load(is, CLIENT_TRUST_PASSWORD.toCharArray());
} finally {
is.close();
}
//初始化密钥管理器
trustManager.init(tks);
//初始化SSLContext
sslContext.init(null, trustManager.getTrustManagers(), null);
} catch (Exception e) {
Log.e("SslContextFactory", e.getMessage());
}
return sslContext;
}
}
2.在用Retrofit网络请求时,添加对应代码
SSLSocketFactory sslSocketFactory = new SslContextFactory().getSslSocket(context).getSocketFactory();
OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder().sslSocketFactory(sslSocketFactory);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.*****.com/")
.client(okHttpClient.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
3.这样就可以成功啦。