Android ssl:javax.net.ssl.SSLPeerUnverifiedException:没有对等证书(又一次)

Posted

技术标签:

【中文标题】Android ssl:javax.net.ssl.SSLPeerUnverifiedException:没有对等证书(又一次)【英文标题】:Android ssl: javax.net.ssl.SSLPeerUnverifiedException: No peer certificate (yet again) 【发布时间】:2012-08-09 00:54:06 【问题描述】:

我有一个网站,我正在为 RESTful 服务启用 ssl。我们已经注册了 RapidSSL,安装了证书,它通过了RapidSSL checker。我可以使用各种浏览器访问该站点,包括 android 浏览器(内置、firefox 和 opera),没有任何问题,没有警告。

但是,当我尝试使用我的 android 应用程序访问它时,出现以下异常:

08-11 20:04:05.586   363   381 E HttpProvider: Error executing request: No peer certificate
08-11 20:04:05.586   363   381 E HttpProvider: javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
08-11 20:04:05.586   363   381 E HttpProvider:  at org.apache.harmony.xnet.provider.jsse.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:259)
08-11 20:04:05.586   363   381 E HttpProvider:  at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:93)
08-11 20:04:05.586   363   381 E HttpProvider:  at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:381)
08-11 20:04:05.586   363   381 E HttpProvider:  at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:164)
08-11 20:04:05.586   363   381 E HttpProvider:  at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
08-11 20:04:05.586   363   381 E HttpProvider:  at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
08-11 20:04:05.586   363   381 E HttpProvider:  at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:359)
08-11 20:04:05.586   363   381 E HttpProvider:  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
08-11 20:04:05.586   363   381 E HttpProvider:  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
08-11 20:04:05.586   363   381 E HttpProvider:  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
08-11 20:04:05.586   363   381 E HttpProvider:  at com.xxxxx.netlib.http.HttpProvider.executeRequest(HttpProvider.java:75)

这发生在模拟器上的 android 2.3.3 和 3.2 平板电脑上。我已经看到很多关于此的点击,但我发现没有任何东西可以帮助我解决这个问题。

更多数据:

$ openssl s_client -CAfile www.xxxxx.com.pem -connect www.xxxxx.com:443
CONNECTED(00000003)
depth=3 C = US, O = Equifax, OU = Equifax Secure Certificate Authority
verify return:1
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify return:1
depth=1 C = US, O = "GeoTrust, Inc.", CN = RapidSSL CA
verify return:1
depth=0 serialNumber = 1-7wArtEjdTwJ94d5iVDooDmmC4mXyVj, OU = GT82425783, OU = See www.rapidssl.com/resources/cps (c)12, OU = Domain Control Validated - RapidSSL(R), CN = www.xxxxx.com
verify return:1
---
Certificate chain
0 s:/serialNumber=1-7wArtEjdTwJ94d5iVDooDmmC4mXyVj/OU=GT82425783/OU=See www.rapidssl.com/resources/cps (c)12/OU=Domain Control Validated - RapidSSL(R)/CN=www.xxxxx.com
  i:/C=US/O=GeoTrust, Inc./CN=RapidSSL CA
1 s:/C=US/O=GeoTrust, Inc./CN=RapidSSL CA
  i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
  i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---
[snip]

我为设置客户端而运行的代码:

public class HttpProvider implements INetworkProvider 
  private static final String LOG = "HttpProvider";
  protected DefaultHttpClient client;

  public HttpProvider() 
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    final SSLSocketFactory sslSocketFactory = SSLSocketFactory.getSocketFactory();
    sslSocketFactory.setHostnameVerifier(SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
    registry.register(new Scheme("https", sslSocketFactory, 443));

    client = new DefaultHttpClient(
      new ThreadSafeClientConnManager((new BasicHttpParams()), registry), new BasicHttpParams()
    );
  
[snip]

我也尝试过使用 STRICT_HOSTNAME_VERIFIER,但仍然不满意。

据我了解,我不需要设置任何自定义信任库或密钥库,因为我已向公认的证书提供商注册。

我对 ssl 很陌生,发现我在三个字母缩写词的海洋中游泳,我希望这里的人能够帮助我朝着正确的方向前进。

【问题讨论】:

我已经弄清楚如何转储系统信任存储,但我没有在其中看到 RapidSSL,尽管帖子说它在蜂窝中。我将尝试创建自己的信任库,看看会发生什么。 试试这个:***.com/a/38598593/2301721(使用 HttpsURLConnection) 【参考方案1】:

经过大量的挖掘和实验,我终于意识到我使用的 url 有硬编码端口 80 而不是默认为 443。愚蠢的愚蠢。

Trusting all certificates using HttpClient over HTTPS 这个问题的答案极大地帮助了我理解 SSL。

【讨论】:

以上是关于Android ssl:javax.net.ssl.SSLPeerUnverifiedException:没有对等证书(又一次)的主要内容,如果未能解决你的问题,请参考以下文章

javax.net.ssl.SSLHandshakeException:在 Android 7.0 中握手失败

Android 7.0:'javax.net.ssl.SSLHandshakeException:连接被对等方关闭

javax.net.ssl.SSLException:SSL 握手中止连接由对等方重置,同时调用 web 服务 Android

com.android.volley.NoConnectionError:javax.net.ssl.SSLHandshakeException:握手失败

改造 2.2.0 Android API 24 javax.net.ssl.SSLHandshakeException:握手失败

HTTP FAILED:javax.net.ssl.SSLHandshakeException:链验证失败[重复]