Android 用自签名证书实现https请求

Android 用自签名证书实现https请求

一.概要

为了保护用户的信息安全、保护自己的商业利益,减少攻击面,我们需要保障通信信道的安全,采用开发方便的HTTPS是比较好的方式,比用私有协议要好,省时省力。但是如果HTTPS使用不当,就很难起到应有的保护效果。例如有人为了省事选择信任所有证书的方式绕过证书的认证,这样https的作用就完全没意义了。下面我就用Android比较流行的网络框架okhttp来做使用https,包括单向认证和双向认证 

二.OpenSSL生成证书

网上很多如何生成自签名证书的资料,这里就不详细说明,大概步骤如下:
1.生成私钥server.key
2.生成server.crt CA根证书(公钥)
3.用根证书给客户端签发证书server.cer

三.单向认证

把服务器颁发的证书server.cer放到Android的目录assets
/**
 * 添加证书
 *
 */
public static SSLSocketFactory getSocketFactory() {
    try {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null);
        InputStream is = mContext.getAssets().open("server.cer");
        keyStore.setCertificateEntry("0", certificateFactory.generateCertificate(is));
        if (is!=null){
            is.close();
        }
        SSLContext sslContext = SSLContext.getInstance("TLS");

        TrustManagerFactory trustManagerFactory =
                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

        trustManagerFactory.init(keyStore);
        sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
        return sslContext.getSocketFactory();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
然后
mOkHttpClient.setSslSocketFactory(getSocketFactory());

就这样就实现了配置okhttp的https请求

另外如果后台服务器用是nginx搭建的可以先配置
ssl on;
ssl_certificate ...server.crt;
ssl_certificate_key ...server.key;
然后Android客户端直接使用server.crt来代替server.cer,利用nginx来认证https请求,省去了客户端到多台服务器的认证。

四.双向认证

首先对于双向证书验证,也就是说,客户端也会有个“.key文件”,服务器那边会同时有个“.cer文件”与之对应。

我们已经生成了server.key和server.cer文件。

接下来按照生成证书的方式,再生成一对这样的文件,我们命名为:client.key,client.cer.

然后配置服务器
 <Connector  其他属性与前面一致  
    clientAuth="true"
    truststoreFile="client.cer" 
  /> 

配置Android端:
还记得我们单向认证时
sslContext.init(null, trustManagerFactory.getTrustManagers(), 
new SecureRandom());

sslContext.init的第一个参数我们传入的是null,第一个参数的类型实际上是KeyManager[] km,主要就用于管理我们客户端的key。

另外我们生成的客户端client.key是jks格式的文件,java平台才能识别,Android直接用会报错:Java.io.IOException: Wrong version of key store。所有Android端要转成bks格式,可以用转换工具Portecle,网上很多资料可以参考,这里就不详说了。

然后就是我们Android端的代码实现:
/**
 * 添加证书
 *
 */
public static SSLSocketFactory getSocketFactory() {
    try {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null);
        InputStream is = mContext.getAssets().open("server.cer");
        keyStore.setCertificateEntry("0", certificateFactory.generateCertificate(is));
        if (is!=null){
            is.close();
        }
        SSLContext sslContext = SSLContext.getInstance("TLS");

        TrustManagerFactory trustManagerFactory =
                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

        trustManagerFactory.init(keyStore);

        //初始化keystore
        KeyStore clientKeyStore = KeyStore.getInstance("BKS");
        clientKeyStore.load(mContext.getAssets().open("client.bks"), "123456".toCharArray());
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(clientKeyStore, "123456".toCharArray());

        sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
        return sslContext.getSocketFactory();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
"123456"为证书密码

总结

由于项目需要用到https,而之前也没有接触过,花了几天搜罗了很多资料,最后找到了实践可行的的方法,现在分享出来,希望对大家有帮助,如果有理解错误的地方,请指出,谢谢!
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值