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。它们不同且不兼容。 请记住,从安全角度来看,使用无操作TrustManager
和 ALLOW_ALL_HOSTNAME_VERIFIER
是非常值得怀疑的。如果目标是连接到测试环境,很好,但请不要将此代码投入生产。
super(null); 行出现错误,表示 构造函数 SSLSocketFactory(KeyStore) 不明确。
@ThinkChris 尝试将该 null 转换为 SSLContext 实例。超级((SSLContext) null);以上是关于Android:发出 Https 请求的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Phonegap 插件(适用于 Android)向 API 发出简单的 json 发布请求?