【问题标题】:How to support Comodo SSL cert in loopj on Android?如何在 Android 上的 loopj 中支持 Comodo SSL 证书?
【发布时间】:2015-04-21 05:15:47
【问题描述】:

我正在运行一个使用 HTTPS 和来自 Comodo 的 SSL 证书的站点。 Qualys 为该站点提供了 A+ 分数,并且相同的 URL 在 Android 上的 Chrome 中可以正常工作。当我尝试使用 loopj 从 Android 应用程序连接到该站点时,我收到了 SSLPeerUnverifiedException 异常。我必须手动提供证书信息吗?

我在默认的 AsyncHttpClient 示例中看到了这种行为:

AsyncHttpClient client = new AsyncHttpClient();
client.get("https://myapp.com", new AsyncHttpResponseHandler() {

    @Override
    public void onStart() {
        // called before request is started
    }

    @Override
    public void onSuccess(int statusCode, Header[] headers, byte[] response) {
        // called when response HTTP status is "200 OK"
    }

    @Override
    public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
        // called when response HTTP status is "4XX" (eg. 401, 403, 404)
    }

    @Override
    public void onRetry(int retryNo) {
        // called when request is retried
    }
});

例外:

04-20 21:59:57.092: W/System.err(8824): javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
04-20 21:59:57.102: W/System.err(8824):     at com.android.org.conscrypt.SSLNullSession.getPeerCertificates(SSLNullSession.java:104)
04-20 21:59:57.102: W/System.err(8824):     at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:93)
04-20 21:59:57.102: W/System.err(8824):     at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:388)
04-20 21:59:57.102: W/System.err(8824):     at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:214)
04-20 21:59:57.102: W/System.err(8824):     at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:167)
04-20 21:59:57.102: W/System.err(8824):     at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:125)
04-20 21:59:57.102: W/System.err(8824):     at org.apache.http.impl.client.DefaultRequestDirector.executeSB(DefaultRequestDirector.java:831)
04-20 21:59:57.102: W/System.err(8824):     at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:697)
04-20 21:59:57.102: W/System.err(8824):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:575)
04-20 21:59:57.102: W/System.err(8824):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:491)
04-20 21:59:57.102: W/System.err(8824):     at com.loopj.android.http.AsyncHttpRequest.makeRequest(AsyncHttpRequest.java:147)
04-20 21:59:57.102: W/System.err(8824):     at com.loopj.android.http.AsyncHttpRequest.makeRequestWithRetries(AsyncHttpRequest.java:178)
04-20 21:59:57.102: W/System.err(8824):     at com.loopj.android.http.AsyncHttpRequest.run(AsyncHttpRequest.java:109)
04-20 21:59:57.102: W/System.err(8824):     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
04-20 21:59:57.102: W/System.err(8824):     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
04-20 21:59:57.102: W/System.err(8824):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
04-20 21:59:57.102: W/System.err(8824):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
04-20 21:59:57.102: W/System.err(8824):     at java.lang.Thread.run(Thread.java:818)

【问题讨论】:

    标签: android ssl loopj


    【解决方案1】:

    作为 loopj 的替代方案,您可以创建一个 AsyncTask 来执行 程序上的任务。几乎与循环相同的方式是这样做的。我使用下面的类来执行 HTTP/S 请求,它完成了这项工作。

    class GetHTTPSTask extends AsyncTask<Void, Void, Boolean>
      {
        private String mUrl;
    
        public GetHTTPSTask(String url)
        {
          this.mUrl = url;
        }
    
        @Override
        protected Boolean doInBackground(Void... params)
        {
          try
          {
            URL urlConnection = new URL(mUrl);
            HttpURLConnection connection = (HttpURLConnection) urlConnection
              .openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream input = connection.getInputStream();
    
            return Boolean.TRUE;
          }
          catch (Exception e)
          {
            e.printStackTrace();
          }
          return null;
        }
        @Override
        protected void onPostExecute(Boolean result)
        {
          if ( result != null)
          {
            // Connection was successful
            // Do something here
          }
          super.onPostExecute(result);
        }
      }
    

    并使用它:

    new GetHTTPSTask("https://www.google.com/").execute();
    

    【讨论】:

      【解决方案2】:

      如果您使用的是 Apache 库,那么服务器就不能依赖 SNI。

      如果您可以控制服务器,则可以将其配置为具有唯一 IP。或者,修复客户端:

      来自Android docs

      幸运的是,HttpsURLConnection 从 Android 2.3 开始就支持 SNI。 不幸的是,Apache HTTP 客户端没有,这是众多客户端之一 我们不鼓励使用它的原因。如果您需要支持,一种解决方法 Android 2.2(和更早版本)或 Apache HTTP 客户端是设置一个 唯一端口上的替代虚拟主机,以便明确 返回哪个服务器证书。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-13
        • 1970-01-01
        • 2016-06-29
        • 1970-01-01
        • 1970-01-01
        • 2017-05-25
        相关资源
        最近更新 更多