首页 技术 正文
技术 2022年11月10日
0 收藏 391 点赞 4,785 浏览 5570 个字

项目中Android https请求地址遇到了这个异常(无终端认证):

javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

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

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

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

<span style="font-family:Times New Roman;font-size:14px;">/**  * Post请求连接Https服务  * @param serverURL  请求地址  * @param jsonStr    请求报文  * @return  * @throws Exception  */ public static synchronized String doHttpsPost(String serverURL, String jsonStr)throws Exception {     <span style="color:#009900;">// 参数 </span>     HttpParams httpParameters = new BasicHttpParams();    <span style="color:#33cc00;"> </span><span style="color:#009900;">// 设置连接超时 </span>     HttpConnectionParams.setConnectionTimeout(httpParameters, 3000);     <span style="color:#009900;">// 设置socket超时 </span>     HttpConnectionParams.setSoTimeout(httpParameters, 3000);     <span style="color:#009900;">// 获取HttpClient对象 (认证) </span>     HttpClient hc = initHttpClient(httpParameters);     HttpPost post = new HttpPost(serverURL);    <span style="color:#006600;"> </span><span style="color:#009900;">// 发送数据类型 </span>     post.addHeader("Content-Type", "application/json;charset=utf-8");    <span style="color:#009900;"> // 接受数据类型 </span>     post.addHeader("Accept", "application/json");   <span style="background-color: rgb(255, 255, 255);"><span style="color:#006600;"> </span><span style="color:#009900;"> // 请求报文 </span></span>     StringEntity entity = new StringEntity(jsonStr, "UTF-8");     post.setEntity(entity);     post.setParams(httpParameters);     HttpResponse response = null;     try {         response = hc.execute(post);     } catch (UnknownHostException e) {         throw new Exception("Unable to access " + e.getLocalizedMessage());     } catch (SocketException e) {         e.printStackTrace();     }     int sCode = response.getStatusLine().getStatusCode();     if (sCode == HttpStatus.SC_OK) {         return EntityUtils.toString(response.getEntity());     } else         throw new Exception("StatusCode is " + sCode); }  private static HttpClient client = null; /**  * 初始化HttpClient对象  * @param params  * @return  */ public static synchronized HttpClient initHttpClient(HttpParams params) {     if(client == null){         try {             KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());             trustStore.load(null, null);              SSLSocketFactory sf = new SSLSocketFactoryImp(trustStore);             //允许所有主机的验证             sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);              HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);             HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);             // 设置http和https支持             SchemeRegistry registry = new SchemeRegistry();             registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));             registry.register(new Scheme("https", sf, 443));              ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);              return new DefaultHttpClient(ccm, params);         } catch (Exception e) {             e.printStackTrace();             return new DefaultHttpClient(params);         }     }     return client; } public static class SSLSocketFactoryImp extends SSLSocketFactory {     final SSLContext sslContext = SSLContext.getInstance("TLS");      public SSLSocketFactoryImp(KeyStore truststore)             throws NoSuchAlgorithmException, KeyManagementException,             KeyStoreException, UnrecoverableKeyException {         super(truststore);          TrustManager tm = new X509TrustManager() {             public java.security.cert.X509Certificate[] getAcceptedIssuers() {                 return null;             }              @Override             public void checkClientTrusted(                     java.security.cert.X509Certificate[] chain,                     String authType)                     throws java.security.cert.CertificateException {             }              @Override             public void checkServerTrusted(                     java.security.cert.X509Certificate[] chain,                     String authType)                     throws java.security.cert.CertificateException {             }         };         sslContext.init(null, new TrustManager[] { tm }, null);     }      @Override     public Socket createSocket(Socket socket, String host, int port,             boolean autoClose) throws IOException, UnknownHostException {         return sslContext.getSocketFactory().createSocket(socket, host,                 port, autoClose);     }      @Override     public Socket createSocket() throws IOException {         return sslContext.getSocketFactory().createSocket();     } }</span> 

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.把证书添加为信任。

<span style="font-family:Times New Roman;font-size:14px;">public static String requestHTTPSPage(Context context, String mUrl) {        InputStream ins = null;        String result = "";        try {            ins = context.getAssets().open("my.key"); // 下载的证书放到项目中的assets目录中            CertificateFactory cerFactory = CertificateFactory.getInstance("X.509");            Certificate cer = cerFactory.generateCertificate(ins);            KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");            keyStore.load(null, null);            keyStore.setCertificateEntry("trust", cer);             SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore);            Scheme sch = new Scheme("https", socketFactory, 443);            HttpClient mHttpClient = new DefaultHttpClient();            mHttpClient.getConnectionManager().getSchemeRegistry().register(sch);             BufferedReader reader = null;            try {                HttpGet request = new HttpGet();                request.setURI(new URI(mUrl));                HttpResponse response = mHttpClient.execute(request);                if (response.getStatusLine().getStatusCode() != 200) {                    request.abort();                    return result;                }                 reader = new BufferedReader(new InputStreamReader(response                        .getEntity().getContent()));                StringBuffer buffer = new StringBuffer();                String line = null;                while ((line = reader.readLine()) != null) {                    buffer.append(line);                }                result = buffer.toString();            } catch (Exception e) {                e.printStackTrace();            } finally {                if (reader != null) {                    reader.close();                }            }        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                if (ins != null)                    ins.close();            } catch (IOException e) {                e.printStackTrace();            }        }        return result; </span>
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,491
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,907
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,740
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,492
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,132
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,293