如何在Android上的loopj中支持Comodo SSL证书?

时间:2015-04-21 05:15:48

标签: android ssl loopj

我使用来自Comodo的SSL证书使用HTTPS运行网站。 Qualys为网站提供了A +分数,并且相同的网址在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)

2 个答案:

答案 0 :(得分: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();

答案 1 :(得分:0)

如果你正在使用Apache库,那么服务器不能依赖SNI。

如果您拥有对服务器的控制权,则可以配置它具有唯一的IP。或者,修复客户端:

来自Android docs

  

幸运的是,自Android 2.3以来,HttpsURLConnection支持SNI。   不幸的是,Apache HTTP Client没有,这是众多之一   我们不鼓励使用它的原因。一个解决方法,如果您需要支持   Android 2.2(及更早版本)或Apache HTTP Client是设置的   唯一端口上的备用虚拟主机,因此它是明确的   要返回的服务器证书。