AndroidHttpClient需要更多信息。自签名SSL。可能?

时间:2011-04-13 19:53:50

标签: android

关于AndroidHttpClient的信息很少,特别是我找不到任何好的例子。从我读到的 - 我可以使用此客户端,它已预先配置为SSL。我的目标是2.2+,所以它对我很有用。

  1. 关于我如何使用它有什么好的样本吗?特别适用于REST服务POST
  2. 是否有关于如何允许自签名证书的样本?我不介意只允许任何证书与将特定证书导入本地商店。
  3. 谢谢!

    我自己的回答(见下面的代码)。

    1. 我的IIS服务器带有自签名证书。我不得不采取额外步骤并生成与外部名称匹配的证书,而不是服务器名称。
    2. 我使用AndroidHttpClient。据说,这个客户端具有Android的所有“正确”设置,并从版本8开始支持
    3. 我在Application对象中创建AndroidHttpClient并在其中共享。
    4. 我在注入自定义证书时将代码分开,以便以后轻松删除它。我注意到在App启动时需要花时间从资源加载证书。
    5. 我的应用程序单例版本。请参阅顶部的注释,详细了解我用于生成所有内容的命令行。始终使用相同的密码以确保其有效。 PKS文件密码必须匹配。

      import android.net.http.AndroidHttpClient;
      import android.app.Application;
      import android.util.Log;
      import idatt.mobile.android.providers.DBLog;
      import org.apache.http.conn.ClientConnectionManager;
      import org.apache.http.conn.scheme.Scheme;
      import org.apache.http.conn.scheme.SchemeRegistry;
      import org.apache.http.conn.ssl.SSLSocketFactory;
      
      import java.io.InputStream;
      import java.security.KeyStore;
      
      /*
      To generate PKS:
      1. Created cert in IIS7 and then exported as pfx. Follow instruction on SelfSSL: http://www.robbagby.com/iis/self-signed-certificates-on-iis-7-the-easy-way-and-the-most-effective-way/
      1a. Download tool: http://cid-3c8d41bb553e84f5.skydrive.live.com/browse.aspx/SelfSSL
      1b. Run: SelfSSL /N:CN=mydomainname /V:1000 /S:1 /P:8081
       I use port 8081 on my server
      1c. Export from IIS manager to cert.pfx
      2. Run command line in SSL to convert file into X.509:
      openssl pkcs12 -in C:\cert.pfx -out C:\cert.cer -nodes
      3. Edit file and delete all except -----BEGIN.... END CERTIFICATE----- IMPORTANT! It was working when I got proper (5) amount of dashes and put tags and data on separate lines
      4. use keytool. C:\Java\JDK\bcprov.jar was downloaded separately
       C:\Users\Ivan>keytool -import -v -trustcacerts -alias key_alias -file C:\cert.cer -keystore C:\mystore.bks -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath C:\Java\JDK\bcprov.jar -storepass 123456
      
      */
      
      public class MyApplication extends Application
      {
          private static final String LOG_TAG = "MyApplication";
          private AndroidHttpClient androidHttpClient;
      
          @Override
          public void onCreate()
          {
              super.onCreate();
              androidHttpClient = createAndroidHttpClient();
          }
      
          @Override
          public void onLowMemory()
          {
              super.onLowMemory();
              shutdownAndroidHttpClient();
          }
      
          @Override
          public void onTerminate()
          {
              super.onTerminate();
              shutdownAndroidHttpClient();
          }
      
      
          private AndroidHttpClient createAndroidHttpClient()
          {
              Log.d(LOG_TAG,"createAndroidHttpClient");
      
              AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
      
              //This is optional call to inject custom BKS that was created from self-signed certificate
              client = addCustomCertificate(client);
      
              return client;
          }
      
          public AndroidHttpClient getAndroidHttpClient()
          {
              return androidHttpClient;
          }
      
          private void shutdownAndroidHttpClient()
          {
              if(androidHttpClient!=null && androidHttpClient.getConnectionManager()!=null)
              {
                  androidHttpClient.getConnectionManager().shutdown();
              }
          }
      
          private AndroidHttpClient addCustomCertificate(AndroidHttpClient client)
          {
              SSLSocketFactory sf = SSLSocketFactory.getSocketFactory();
      
              try
              {
                  InputStream in = getResources().openRawResource(R.raw.home_server);
      
                  KeyStore trustStore = KeyStore.getInstance("BKS");
      
                  trustStore.load(in, "123456".toCharArray());
                  in.close();
      
                  sf = new SSLSocketFactory(trustStore);
                  sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
              }
              catch (Exception t)
              {
                  DBLog.InsertError(this, t);
              }
      
              //Lets register our custom factory here
              client.getConnectionManager().getSchemeRegistry().register(new Scheme("https", sf, 443));
      
              return client;
          }
      }
      

      以下是我如何使用此客户端(我在AsyncTask中调用它)

      private String processPOST(String url, String requestData)
      {
          String responseData = null;
          application = (MyApplication)getApplication();
          AndroidHttpClient client = application.getAndroidHttpClient();
          HttpPost request = new HttpPost(url);
      
          try
          {
              StringEntity entity = new StringEntity(requestData);
              entity.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
              request.setEntity(entity);
              ResponseHandler<String> handler = new BasicResponseHandler();
              responseData = client.execute(request, handler);
          }
          catch (Throwable e)
          {
              DBLog.InsertError(ctxt, e);
          }
      
          return responseData;
      }
      

      这种组合似乎100%适用于2.2和2.3设备。当我使用DefaultHttpClient的代码片段时,我遇到了2.3.1超时请求(Nexus S)的问题

4 个答案:

答案 0 :(得分:5)

您可以使用Apache HttpClient。

    public HttpClient getNewHttpClient() {
    try {
        KeyStore trustStore = KeyStore.getInstance("BKS");
        InputStream in = getResources().openRawResource(R.raw.mykeystore);
        try {
            trustStore.load(in, "mypassword".toCharArray());
        } finally {
            in.close();
        }

        SSLSocketFactory sf = new SSLSocketFactory(trustStore);
        sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);

        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", sf, 443));

        ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
        return new DefaultHttpClient(ccm, params);
    } catch (Exception e) {
        return new DefaultHttpClient();
    }
}

在Web服务器中,IIS可以创建自签名证书并导出为PFX,然后使用openssl工具将其转换为PEM,将其编辑为仅使用证书,然后使用JDK和Bouncy Castle的keytool创建包含证书的密钥库罐。可以将创建的密钥库导入到项目中,如上面的代码所示。

答案 1 :(得分:0)

我使用'信任所有'SSL连接进行了一些测试:HTTPS GET (SSL) with Android and self-signed server certificate

希望它有所帮助:D

答案 2 :(得分:-1)

你可以找到一个example here - 唯一不寻常的是,如果遥控器返回一个401(?)代码,你将无法通过connection.getResponseCode()得到它,但是异常会被抛出(也许是5xx)。

以上示例在SSL上运行,因此可以使用https。我不知道有关自签名证书的任何信息。我想我记得有人说他们有问题,但我不确定。

答案 3 :(得分:-1)

Android集成了Apache http client component。如果查看链接的文档部分,您将找到教程和示例。

如果你搜索Apache Http Client而不是Android Http Client,你会发现很多信息。

编辑:哦 - 我刚才意识到Android中有一个AndroidHttpClient类。从未使用过它。看看帮助我的this答案。