项目中Android https请求地址遇到了这个异常(无终端认证):
javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

是SSL协议中没有终端认证。

没有遇到过的问题,于是无奈的去找度娘。。。。。。。

看了不少大神的博客后得到的解决方案如下:

/***Post请求连接Https服务*@paramserverURL请求地址*@paramjsonStr请求报文*@return*@throwsException*/publicstaticsynchronizedStringdoHttpsPost(StringserverURL,StringjsonStr)throwsException{//参数HttpParamshttpParameters=newBasicHttpParams();//设置连接超时HttpConnectionParams.setConnectionTimeout(httpParameters,3000);//设置socket超时HttpConnectionParams.setSoTimeout(httpParameters,3000);//获取HttpClient对象(认证)HttpClienthc=initHttpClient(httpParameters);HttpPostpost=newHttpPost(serverURL);//发送数据类型post.addHeader("Content-Type","application/json;charset=utf-8");//接受数据类型post.addHeader("Accept","application/json");//请求报文StringEntityentity=newStringEntity(jsonStr,"UTF-8");post.setEntity(entity);post.setParams(httpParameters);HttpResponseresponse=null;try{response=hc.execute(post);}catch(UnknownHostExceptione){thrownewException("Unabletoaccess"+e.getLocalizedMessage());}catch(SocketExceptione){e.printStackTrace();}intsCode=response.getStatusLine().getStatusCode();if(sCode==HttpStatus.SC_OK){returnEntityUtils.toString(response.getEntity());}elsethrownewException("StatusCodeis"+sCode);}privatestaticHttpClientclient=null;/***初始化HttpClient对象*@paramparams*@return*/publicstaticsynchronizedHttpClientinitHttpClient(HttpParamsparams){if(client==null){try{KeyStoretrustStore=KeyStore.getInstance(KeyStore.getDefaultType());trustStore.load(null,null);SSLSocketFactorysf=newSSLSocketFactoryImp(trustStore);//允许所有主机的验证sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);HttpProtocolParams.setVersion(params,HttpVersion.HTTP_1_1);HttpProtocolParams.setContentCharset(params,HTTP.UTF_8);//设置http和https支持SchemeRegistryregistry=newSchemeRegistry();registry.register(newScheme("http",PlainSocketFactory.getSocketFactory(),80));registry.register(newScheme("https",sf,443));ClientConnectionManagerccm=newThreadSafeClientConnManager(params,registry);returnnewDefaultHttpClient(ccm,params);}catch(Exceptione){e.printStackTrace();returnnewDefaultHttpClient(params);}}returnclient;}publicstaticclassSSLSocketFactoryImpextendsSSLSocketFactory{finalSSLContextsslContext=SSLContext.getInstance("TLS");publicSSLSocketFactoryImp(KeyStoretruststore)throwsNoSuchAlgorithmException,KeyManagementException,KeyStoreException,UnrecoverableKeyException{super(truststore);TrustManagertm=newX509TrustManager(){publicjava.security.cert.X509Certificate[]getAcceptedIssuers(){returnnull;}@OverridepublicvoidcheckClientTrusted(java.security.cert.X509Certificate[]chain,StringauthType)throwsjava.security.cert.CertificateException{}@OverridepublicvoidcheckServerTrusted(java.security.cert.X509Certificate[]chain,StringauthType)throwsjava.security.cert.CertificateException{}};sslContext.init(null,newTrustManager[]{tm},null);}@OverridepublicSocketcreateSocket(Socketsocket,Stringhost,intport,booleanautoClose)throwsIOException,UnknownHostException{returnsslContext.getSocketFactory().createSocket(socket,host,port,autoClose);}@OverridepublicSocketcreateSocket()throwsIOException{returnsslContext.getSocketFactory().createSocket();}}
run下,小手发抖的点到测试按钮,深吸口气,咦?没反应。。。马蛋的,工作线程忘记start(),唉,再次run下,终于的有点反应了,神奇的竟然没有报之前的 javax.net.ssl.SSLPeerUnverifiedException: No peer certificate 的异常了。服务端的数据正常返回了。,狂喜中…

分析问题:
HTTPS:超文本安全传输协议,和HTTP相比,多了一个SSL/TSL的认证过程,端口为443。

1.peer终端发送一个request,https服务端把支持的加密算法等以证书的形式返回一个身份信息(包含ca颁发机构和加密公钥等)。

2.获取证书之后,验证证书合法性。

3.随机产生一个密钥,并以证书当中的公钥加密。

4.request https服务端,把用公钥加密过的密钥传送给https服务端。

5.https服务端用自己的密钥解密,获取随机值。

6.之后双方传送数据都用此密钥加密后通信。

HTTPS流程清楚后,问题也就明显了,验证证书时,无法验证

上面提供的解决方案就是添加默认信任全部证书。以此来通过接下来的通信。


但是,这样问题是解决了。但是觉得还是不带靠谱(信任全部证书有点危险)。继续噼噼啪啪的网上搜索一番。又找到了一种解决方案,其过程大致这样的:

1.浏览器访问https地址,保存提示的证书到本地,放到android项目中的assets目录。

2.导入证书,代码如下。

3.把证书添加为信任。

publicstaticStringrequestHTTPSPage(Contextcontext,StringmUrl){InputStreamins=null;Stringresult="";try{ins=context.getAssets().open("my.key");//下载的证书放到项目中的assets目录中CertificateFactorycerFactory=CertificateFactory.getInstance("X.509");Certificatecer=cerFactory.generateCertificate(ins);KeyStorekeyStore=KeyStore.getInstance("PKCS12","BC");keyStore.load(null,null);keyStore.setCertificateEntry("trust",cer);SSLSocketFactorysocketFactory=newSSLSocketFactory(keyStore);Schemesch=newScheme("https",socketFactory,443);HttpClientmHttpClient=newDefaultHttpClient();mHttpClient.getConnectionManager().getSchemeRegistry().register(sch);BufferedReaderreader=null;try{HttpGetrequest=newHttpGet();request.setURI(newURI(mUrl));HttpResponseresponse=mHttpClient.execute(request);if(response.getStatusLine().getStatusCode()!=200){request.abort();returnresult;}reader=newBufferedReader(newInputStreamReader(response.getEntity().getContent()));StringBufferbuffer=newStringBuffer();Stringline=null;while((line=reader.readLine())!=null){buffer.append(line);}result=buffer.toString();}catch(Exceptione){e.printStackTrace();}finally{if(reader!=null){reader.close();}}}catch(Exceptione){e.printStackTrace();}finally{try{if(ins!=null)ins.close();}catch(IOExceptione){e.printStackTrace();}}returnresult;}

更多相关文章

  1. Android与服务端数据交互 Apache Tomcat + MySQL
  2. Android静态安全检测 -> 证书弱校验
  3. android使用JSON进行网络数据交换(服务端、客户端)的实现
  4. Google Map API V2密钥申请
  5. Android 7.0 之后抓包 unknown 和证书无效的解决方案(无需改代码)
  6. Android WebView与服务端交互Demo
  7. 【android】基于Android的搜索客户端应用团队项目(服务端)
  8. Android 客户端与服务端交互之登陆示例(Android+servlet+JavaBean
  9. android 向服务端发送请求编码问题

随机推荐

  1. EditText(细节) android:maxLines="1"失
  2. Android(安卓)应用初始化及窗体事件的分
  3. 在Netbeans上配置Android开发环境
  4. Android(安卓)玩转Glide4---Transformati
  5. 用Fiddler抓取Android、Iphone网络数据包
  6. 2019 Android开发趋势及必备技术点!
  7. Android启动脚本init.rc
  8. 最封闭的开源系统:话说 Android(安卓)的八
  9. 推荐:Android(安卓)Design 如何设计出优秀
  10. 基于底层事件的录制回放实现