Android与服务端使用Https加密通信

来源:互联网 发布:青年网络公开课 2017 编辑:程序博客网 时间:2024/06/06 01:05

Https证书

现在网络安全越来越受重视,通用做法是采用https加密通信,使用https需要数字证书,只有合法的证书才能被浏览器、操作系统默认支持,而所谓的合法证书是在CA公司那购买的(原来我们的合法性是花钱从别人那买来的,不得不吐槽这种互联网安全设计真是坑爹),虽然现在也有一些免费CA证书,但申请还是挺麻烦,这里我们使用自己生成的https证书。

服务端使用https

生成https证书

JDK自带的keytool工具可以很方便生成https证书,可以查看它的使用方法:

比如这条命令就可以生成一个有效期10年的证书:

keytool -genkey -alias spring -validity 3560 -keystore spring.keystore 

服务端配置https证书

服务端一般使用Tomcat、Jetty、Undertow等作为Servlet容器,我们将上面生成的keystore证书放在项目中,然后在配置文件中引入证书即可:

server.ssl.key-store=spring.keystoreserver.ssl.key-alias=springserver.ssl.key-password=passwordserver.ssl.key-store-type=JKS

这样服务端就支持https了,启动项目访问服务就要加https前缀,如 https://localhost:8080/user

Android自定义https校验

如果是花钱买的CA证书是不需要额外配置的,Android系统内部有信任列表,会自行校验通过,这里讲配置自定义https校验。

Android端通常使用 Retrofit 做网络请求,Retrofit底层就是OKhttp,OKhttp实现自定义https校验并不难,主要分三步。

把证书公钥预埋在APP中

这条命令可以导出证书公钥字符串:

keytool -list -rfc -keystore tomcat.keystore

把这个公钥作为一个字符串常量放在项目中供后面校验使用。

自定义证书校验逻辑

使用上面的公钥字符串构建X509TrustManager对象,在checkServerTrusted方法中校验服务端证书:

X509TrustManager trustManager = new X509TrustManager() {    @Override    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {        //校验客户端证书    }    @Override    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {        //校验服务端证书        X509Certificate ca = (X509Certificate) CertificateFactory.getInstance("X.509")                .generateCertificate(new ByteArrayInputStream(PUB_KEY.getBytes()));        for (X509Certificate cert : chain) {            // 检查服务端证书是否过期            cert.checkValidity();            try {                //和APP预埋证书对比                cert.verify(ca.getPublicKey());            } catch (Exception e) {                //证书校验异常                throw new SecurityException("证书错误!");            }        }    }    @Override    public X509Certificate[] getAcceptedIssuers() {        return new X509Certificate[0];    }};

注意证书校验异常时抛出一个SecurityException,如果不抛出这个RuntimeException,程序会继续执行,请求依然正常,证书校验就没有意义。

设置OkHttpClient校验证书

然后使用上面的trustManager构建OkHttpClient

SSLSocketFactory sslSocketFactory = null;try {    SSLContext sslContext = SSLContext.getInstance("TLS");    sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom());    sslSocketFactory = sslContext.getSocketFactory();} catch (NoSuchAlgorithmException | KeyManagementException e) {    e.printStackTrace();}final HostnameVerifier hostnameVerifier = new HostnameVerifier() {    @Override    public boolean verify(final String hostname,                          final SSLSession session) {        //服务端主机域名地址校验        return true;    }};OkHttpClient client = new OkHttpClient.Builder()        .hostnameVerifier(hostnameVerifier)        .sslSocketFactory(sslSocketFactory, trustManager)        .build();

使用这个配置好的OkHttpClient与服务端交互,就可以支持自定义https证书加密通信了,如果服务端证书不符,请求会自动断开。


扫一扫关注我的微信公众号

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 2岁宝宝大便干燥怎么办 5岁儿童大便干燥怎么办 九个月宝宝平血怎么办 6个月宝宝肛裂怎么办 3岁儿童大便干燥怎么办 外痔疮出血了该怎么办 外痔疮流血了怎么办呢 外痔疮破了出血怎么办 拉稀拉的肛门疼怎么办 大人屁股沟裂了怎么办 肛门痛大便有血怎么办 肛裂出血几天了怎么办 肛裂拉屎出血该怎么办 孕期肛裂出血该怎么办 老人大便拉不出来怎么办 拉屎拉的屁眼疼怎么办 拉屎堵在肛门口怎么办 上火拉大便有血怎么办 7岁儿童大便带血怎么办 阴炎用药后出血怎么办 孕晚期大便拉不出来怎么办 想拉屎拉不出来怎么办 4岁幼儿大便干燥怎么办 2岁幼儿大便干燥怎么办 1岁幼儿大便干燥怎么办 5岁幼儿大便干燥怎么办 4岁儿童大便干燥怎么办 狗吃别的狗的屎怎么办 狗狗黄疸怎么办最有效 拉屎出血但不疼怎么办 没拉出时就出血怎么办 拉不出大便怎么办肛门像被堵住 尿里粘液丝高怎么办 右肋骨里面疼是怎么办 腰受凉直不起来怎么办 干活累了腰疼怎么办 打球腰打球腰疼怎么办 生完孩子腰酸痛怎么办 腰窝哪里痛是怎么办 尿结石疼的时候怎么办 站久了脚底痛怎么办