Android:发出 Https 请求

Posted

技术标签:

【中文标题】Android:发出 Https 请求【英文标题】:Android: Making Https Request 【发布时间】:2011-11-29 03:17:08 【问题描述】:

在发出 Https 请求时,如何避免“javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated”异常和 android Apache lib 间隙“构造函数 SSLSocketFactory(SSLContext) 未定义”?

【问题讨论】:

我有一个适合我的答案。我会在我的 8 小时时间限制到期后的某个时间发布它。来吧 Stack Overflow,让我回答我自己的问题! 您首先需要更多积分 :) 这是我的贡献。 仅供参考,截至撰写本文时(02/2013),此错误似乎已融入某些 HTC 手机固件 【参考方案1】:

我有类似的问题,更像是question,但根本原因与两个问题中提到的完全不同。

我使用 DefaultHttpClient 作为 httpclient 来请求 https://maps.googleapis.com 之类的链接。我正在尝试所有提议的解决方案,但没有一个对我有用。经过几个小时试图解决它,找到了根本原因:我的设备连接到一个访客 WIFI,它可能有一些特定的过滤规则阻止了相关的网络部分。切换到其他网络解决了我的问题。

【讨论】:

【参考方案2】:

此方法接受一个 HttpClient 实例并返回一个准备好 https 的 HttpClient 实例。

 private HttpClient sslClient(HttpClient client) 
    try 
        X509TrustManager tm = new X509TrustManager()  
            public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException 
            

            public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException 
            

            public X509Certificate[] getAcceptedIssuers() 
                return null;
            
        ;
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(null, new TrustManager[]tm, null);
        SSLSocketFactory ssf = new MySSLSocketFactory(ctx);
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        ClientConnectionManager ccm = client.getConnectionManager();
        SchemeRegistry sr = ccm.getSchemeRegistry();
        sr.register(new Scheme("https", ssf, 443));
        return new DefaultHttpClient(ccm, client.getParams());
     catch (Exception ex) 
        return null;
    

由于Android org.apache.http.conn.ssl.SSLSocketFactory 没有SSLSocketFactory(SSLContext) 构造函数,所以我将类扩展如下。

 public class MySSLSocketFactory extends SSLSocketFactory 
     SSLContext sslContext = SSLContext.getInstance("TLS");

     public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException 
         super(truststore);

         TrustManager tm = new X509TrustManager() 
             public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException 
             

             public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException 
             

             public X509Certificate[] getAcceptedIssuers() 
                 return null;
             
         ;

         sslContext.init(null, new TrustManager[]  tm , null);
     

     public MySSLSocketFactory(SSLContext context) throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException 
        super(null);
        sslContext = context;
     

     @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();
     

优秀文章在这里:http://javaskeleton.blogspot.com/2010/07/avoiding-peer-not-authenticated-with.html

还有一些帮助:Trusting all certificates using HttpClient over HTTPS

【讨论】:

老兄,太棒了!这对我帮助很大! 谢谢,如果没有你的帮助,我真的会迷路的!请注意实现此答案的其他人:请注意您已包含 org.apache.http.conn.ssl.SSLSocketFactory,而不是 javax.net.ssl.SSLSocketFactory。它们不同且不兼容。 请记住,从安全角度来看,使用无操作 TrustManagerALLOW_ALL_HOSTNAME_VERIFIER 是非常值得怀疑的。如果目标是连接到测试环境,很好,但请不要将此代码投入生产。 super(null); 行出现错误,表示 构造函数 SSLSocketFactory(KeyStore) 不明确。 @ThinkChris 尝试将该 null 转换为 SSLContext 实例。超级((SSLContext) null);

以上是关于Android:发出 Https 请求的主要内容,如果未能解决你的问题,请参考以下文章

使用 Android Volley 发出 HTTPS 请求

如何在改造中使用 ssl 证书发出 https 请求

如何使用 Phonegap 插件(适用于 Android)向 API 发出简单的 json 发布请求?

如何在 Android (Facebook SDK v4) 上发出 Facebook 游戏请求后获取收件人 ID?

Android 使用通知

Android Studio手机来指定短信就发出震动和铃声?如何编程?