Android or java https ssl exception

详细分析Android及Java中访问https请求exception(SSLHandshakeException, SSLPeerUnverifiedException)的原因及解决方法。
1、现象
用Android(或Java)测试程序访问下面两个链接。
https链接一:web服务器为jetty,后台语言为java。
https链接二:web服务器为nginx,后台语言为php。
链接一能正常访问,访问链接二报异常,且用HttpURLConnection和apache的HttpClient两种不同的api访问异常信息不同,具体如下:
(1) 用HttpURLConnection访问,测试代码如下:

HttpURLConnection访问https

异常信息为:


1


javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

(2) 用apache的HttpClient访问,测试代码如下:

HttpClient访问https

异常信息为:


1


javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

2、原因分析
需要快速寻求答案的可直接看第3部分 解决方式,这部分详细分析原因。
google发现stackoverflow上不少人反应,twitter和新浪微博的api也会报这个异常,不少人反映客户端需要导入证书,其实大可不必,如果要导证书的话,用户不得哭了。。

从上面的情况可以看出,用jetty做为容器是能正常访问的,只是当容器为nginx时才会异常。

配合后台开发调试了很久,开始以为是cipher suite的问题,为此特地把
ssl_ciphers EDH-RSA-DES-CBC3-SHA;
加入了nginx的配置中,后来发现依然无效。stackoverflow发现,如下代码是能正常访问上面异常的https url

HttpURLConnection访问https并相信所有证书

可以看出其中与之前的HttpsURLConnection测试代码主要的不同就是加入了


1


trustAllHosts();


1


https.setHostnameVerifier(DO_NOT_VERIFY);

表示相信所有证书,并且所有host name验证返回true,这样就能定位到之前的异常是证书验证不通过的问题了。

在上面checkServerTrusted函数中添加断点,查看X509Certificate[] chain的值,即证书信息,发现访问两个不同链接X509Certificate[] chain值有所区别,nginx传过来证书信息缺少了startssl 的ca证书,证书如下:


至此原因大白:
android的证书库里已经带了startssl ca证书,而nginx默认不带startssl ca证书,这样android端访问nginx为容器的https url校验就会失败,jetty默认带startssl ca证书,所以正常
PS:后来对windows和mac下java访问https也做了测试,发现mac上的jdk缺省不带startssl ca证书所以能访问通过,而加上startssl ca证书后同android一样访问不通过。而windows上的jdk缺省带startssl ca证书同android一样访问失败。

3、解决方式
上面的分析中已经介绍了一种解决方法即客户端相信所有证书,不过这种方式只是规避了问题,同时也给客户端带来了风险,比较合适的解决方式是为nginx添加startssl ca证书,添加方法如下:

First, use the StartSSL Control Panel to create a private key and certificate and transfer them to your server. Then execute the following steps (if you use a class 2 certificate replace class1 by class2 in the instructions below):

  • Decrypt the private key by using the password you entered when you created your key:

openssl rsa -in ssl.key -out /etc/nginx/conf/ssl.key

Alternatively you can also use the Tool Box decryption tool of your StartSSL account.

  • Protect your key from prying eyes:

chmod 600 /etc/nginx/conf/ssl.key

  • Fetch the Root CA and Class 1 Intermediate Server CA certificates:

wget http://www.startssl.com/certs/ca.pem
wget http://www.startssl.com/certs/sub.class1.server.ca.pem

  • Create a unified certificate from your certificate and the CA certificates:

cat ssl.crt sub.class1.server.ca.pem ca.pem > /etc/nginx/conf/ssl-unified.crt

  • Configure your nginx server to use the new key and certificate (in the global settings or a server section):

ssl on;
ssl_certificate /etc/nginx/conf/ssl-unified.crt;
ssl_certificate_key /etc/nginx/conf/ssl.key;

  • Tell nginx to reload its configuration:

killall -HUP nginx

时间: 2024-09-10 23:48:57

Android or java https ssl exception的相关文章

浅析Android系统中HTTPS通信的实现_java

前言最近有一个跟HTTPS相关的问题需要解决,因此花时间学习了一下Android平台HTTPS的使用,同时也看了一些HTTPS的原理,这里分享一下学习心得. HTTPS原理HTTPS(Hyper Text Transfer Protocol Secure),是一种基于SSL/TLS的HTTP,所有的HTTP数据都是在SSL/TLS协议封装之上进行传输的.HTTPS协议是在HTTP协议的基础上,添加了SSL/TLS握手以及数据加密传输,也属于应用层协议.所以,研究HTTPS协议原理,最终就是研究S

分享一个Android和java调用RESTful Web服务的利器Resting

分享一个Android和java调用RESTful Web服务的利器Resting   当我们调用Web服务,往往是最终目标是取HTTP响应,将其转化为将在应用中呈现的值对象.Resting可以用来实现这一功能.Resting,在Java的一个轻量级的REST框架,可用于调用一个RESTful Web服务,并转换成响应来自客户端应用程序定制的Java对象.由于它的简单,resting是适合Android等手持设备.   resting目标•暴露简单的get(),post(),put()和dele

zt:Consuming Webservices over HTTPS (SSL)

services|web When Webservices are used, a common concern is security: SOAP messages are transferred in plain text over the network, so anyone with a sniffer could intercept the SOAP message and read it. In my opinion this could happen also to binary

用Go语言写Android应用 (2) - 从Android的Java调用Go代码

用Go语言写Android应用 (2) - 从Android的Java调用Go代码 上一篇我们讲到,Go在Android中的作用,就相当于NDK中的C/C++.上节我们学习了参照NDK的方式用纯Go语言来写应用. 但是,也正如在Android中,C/C++主要是通过JNI的方式被Java代码调用,本节我们就学习如何使用Java代码来调用Go代码. Java调Go的JNI例子 Java部分 我们首先来看这个简单得不能再简单的Java部分的代码,只有一个TextView,然后调用Go写的Hello.

android utils 请求https的问题

问题描述 android utils 请求https的问题 使用xUtils 2.6 框架请求接口,地址是https的 出现javax.net.ssl.SSLException: SSL handshake aborted: ssl=0x61078d10: I/O error during system call, Connection reset by peer 这个错误,搜索了很多结果,不知道如何解决, 有人遇到过这样的问题吗?是怎么解决的呢 解决方案 Android--https请求And

Android 和 Java 内存泄露检测工具——LeakCanary

LeakCanary Android 和 Java 内存泄露检测. "A small leak will sink a great ship." - Benjamin Franklin 千里之堤, 毁于蚁穴. -- <韩非子·喻老> demo 一个非常简单的 LeakCanary demo: https://github.com/liaohuqiu/leakcanary-demo 开始使用 在 build.gradle 中加入引用,不同的编译使用不同的引用: depende

android 开发 java写的 tcp 通信库,注册选择器时异常!跪求java高手指点!!!

问题描述 android 开发 java写的 tcp 通信库,注册选择器时异常!跪求java高手指点!!! public void initialize() throws IOException { boolean done = false; try { Log.e(TAG,"SocketChannel.open:IP:["+hostIp+"Port:"+hostListenningPort+"]."); // 打开监听信道并设置为非阻塞模式 s

求大神帮忙解决 Android项目java空指针异常问题 真的很急 - -

问题描述 求大神帮忙解决 Android项目java空指针异常问题 真的很急 - - 新手小白参考网上教程学习的socket使用,代码几乎雷同老师写的就可以运行我的就会出问题,connect()方法正确可用,但是send()方法不能用,会提示如图空指针异常,但是我真的找不到是哪里的问题,求大神指点.困扰两天了 茶不思饭不想.(由于提问字数问题导包部分代码没有粘过来) 我用Broadcast在一个activity中监听到操作后广播消息过来然后触发java类里面的方法,触发到connect()就可以

Android Studio在线调试Android Framework Java代码

一.准备工作 1.下载最新的Android Studio版本 https://developer.android.com/studio/index.html 当前最新的大版本是2.2 2.下载Android系统源码 这里比较灵活,可以下载公司内部机型的代码,也可以下载原生AOSP的代码 环境配置参考 https://source.android.com/source/initializing.html 源码下载参考 https://source.android.com/source/downlo