超级简单的retrofit使用自签名证书进行HTTPS请求的教程

1. 前言

HTTPS越来越成为主流,谷歌从 2017 年起,Chrome 浏览器将也会把采用 HTTP 协议的网站标记为「不安全」网站;苹果从 2017 年 iOS App 将强制使用 HTTPS;在国内热火朝天的小程序也要求必须使用 HTTPS 请求。那么为什么要使用HTTPS呢?首先说为什么使用https,简单点说就是为了防止数据传输过程中信息被窃取或偷换,防止中间人攻击。

 

 2. 准备BKS证书,将证书放到项目raw目录下

准备.cer文件

可以跟后台开发人员直接拿,也可以直接在网站上下载

在网站上下载:

点击地址栏前面的小锁头,然后点击证书信息

 

 

将.cer转换为.bks

首先要下载bouncycastle的JAR

 

 http://repo2.maven.org/maven2/org/bouncycastle/bcprov-jdk16/1.46/bcprov-jdk16-1.46.jar

 

解压后在当前文件夹执行以下命令

 

keytool -importcert -v -trustcacerts -file “server.cert” -alias server_alias -keystore “server.bks” -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath “bcprov-jdk16-146.jar” -storetype BKS -storepass password

 

黑体字部分是你要修改的,其中 “server.cert”是原cer证书的名字,“server_alias”是别名,“server.bks”是转换后bks证书的名字,“password”是你证书的密码,下边会用到的。

 

成功后将.bks证书文件放到项目的raw目录下。

 

3. 获取SSLSocketFactory

这里是HTTPS证书认证的关键代码,注意password和设置keystore的bks类型一定不要搞错。

 

/** 
 * 获取bks文件的sslsocketfactory 
 * @param context 
 * @return 
 */  
public static SSLSocketFactory getSSLSocketFactory(Context context) {  
    final String CLIENT_TRUST_PASSWORD = "123456";//信任证书密码,该证书默认密码是123456  
    final String CLIENT_AGREEMENT = "TLS";//使用协议  
    final String CLIENT_TRUST_KEYSTORE = "BKS";  
    SSLContext sslContext = null;  
    try {  
        //取得SSL的SSLContext实例  
        sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);  
        //取得TrustManagerFactory的X509密钥管理器实例  
        TrustManagerFactory trustManager = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());  
        //取得BKS密库实例  
        KeyStore tks = KeyStore.getInstance(CLIENT_TRUST_KEYSTORE);  
        InputStream is = context.getResources().openRawResource(R.raw.traint);  
        try {  
            tks.load(is, CLIENT_TRUST_PASSWORD.toCharArray());  
        } finally {  
            is.close();  
        }  
        //初始化密钥管理器  
        trustManager.init(tks);  
        //初始化SSLContext  
        sslContext.init(null, trustManager.getTrustManagers(), null);  
    } catch (Exception e) {  
        e.printStackTrace();  
        Log.e("SslContextFactory", e.getMessage());  
    }  
    return sslContext.getSocketFactory();  
}  

 

  

 

  

4.配置retrofit

String baseUrl = "https://skyish-test.yunext.com";  
int[] certificates = {R.raw.traint};  
    String[] hostUrls = {baseUrl};  
    OkHttpClient client = new okhttp3.OkHttpClient.Builder()  
            .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))  
            .sslSocketFactory(HTTPSUtils.getSSLSocketFactory(context))  
            //.hostnameVerifier(HTTPSUtils.getHostNameVerifier(hostUrls))   
            .readTimeout(10, TimeUnit.SECONDS)  
            .connectTimeout(10, TimeUnit.SECONDS)  
            .build();  
  
    Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl)  
            .addConverterFactory(GsonConverterFactory.create())  
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())  
            .client(client)  
            .build();  

配置好这个就可以使用HTTPS连接了。

 

5.常见错误

SSLContext is not initialized.

 

原因:

1. 证书和证书密码不匹配。

2. 使用了错误的证书。证书类型不对,记得要用bks格式的证书文件。

posted @ 2017-10-24 13:44 所以12138 阅读(...) 评论(...) 编辑 收藏