Android与服务端使用Https加密通信
2017-09-14 19:27
696 查看
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.keystore server.ssl.key-alias=spring server.ssl.key-password=password server.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") 9176 .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构建OkHttpClientSSLSocketFactory 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证书加密通信了,如果服务端证书不符,请求会自动断开。
扫一扫关注我的微信公众号
相关文章推荐
- Android与服务端使用Https加密通信
- 使用Mina框架开发 QQ Android 客户端(2) 客户端与服务端的通信
- android 使用https与服务器进行通信交互
- 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获
- Android handler机制在有序获取服务端通信中的使用
- Android 2.0上使用蓝牙通信代码片断(服务端、客户端、数据传输)
- 如何通过手机客户端Android、Iphone 等访问要求使用客户端证书SSL加密的https网站
- Android客户端与PHP服务端通信(三)---极光推送注册使用
- Android客户端与PHP服务端通信(五)---移植使用极光推送
- 使用RSA对C++ 客户端和 PHP 服务端之间通信的数据进行加密
- android使用https通信总结
- [Android实例] Android 使用HttpClient访问https
- Android网络编程(使用socket进行通信)
- android使用JSON进行网络数据交换(服务端、客户端)的实现
- 使用FDO封装XML&ADO实现与服务端数据通信
- Android通过https协议与服务器端进行通信
- 使用AES加密进行Android的SharedPreferences存储
- Android 使用Handler实现Thread间通信
- 在本地UI使用webview,在html页面用js与android通信方法。
- Windows客户端与Android服务端的Socket通信(USB