2010-02-12 13 views
37

Tüm Http Get/Post öğelerini yapmak için kullanıyorum oldukça basit bir yardımcı sınıfım var. Org.apache.http kütüphanesinden HttpGet, HttpPost ve HttpClient kullanıyorum. Benim tüm şeyler HTTP üzerinden iyi çalışır, ancak HTTPS üzerinde çalışan bir hizmeti tüketmeye çalıştığında, isteği yürütürken bir ClientProtocolException alırım. Kural dışı durumdaki tek ileti "Sunucu geçerli bir HTTP yanıtıyla yanıt veremedi".Android'de Güvenli HTTP Gönderi

Test etmek için, RequestBuilder kullanarak basit bir html formu ve Fiddler2 kullanarak aynı yükü bir tarayıcıdan gönderdim. Geçersiz ve boş yükler yolladım ve hatta yukarıdakilerin tümünü, nesnelerin isteği oluşturma şekliyle ilgili ilginç bir şey olup olmadığını görmek için üstbilgilerle birlikte ve olmadan gönderdim.

Testte kullandığım her şey bana geçerli bir 200 durum HTTP yanıtı veriyor. Hizmet, bana beklediğinden başka bir şey verirse, hatayı açıklayan bir yapı verir.

HTTPS kullanmasını söylemek için HttpPost veya HttpClient nesnelerine eklemem gereken özel bir şey var mı? Açıkça farklı bir bağlantı noktası kullanmasını söylemek zorunda mıyım?

DÜZENLEME: Gerçekten https iletişim için yanlış soket fabrikası kayıtlı

. İşte ben sadece durumda birisi doğru soket fabrikasında ile benim HttpClient nesne oluşturmak için kullanın güncellenmiş yöntem gelecekte bu tür bir sorun aramaların geçerli:

private HttpClient createHttpClient() 
{ 
    HttpParams params = new BasicHttpParams(); 
    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 
    HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET); 
    HttpProtocolParams.setUseExpectContinue(params, true); 

    SchemeRegistry schReg = new SchemeRegistry(); 
    schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 
    schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); 
    ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg); 

    return new DefaultHttpClient(conMgr, params); 
} 
+0

Merhaba Zengin, Gönderiniz için teşekkürler, https on Google hakkında döndürülen tek şey, Google tarafından döndürüldü. Burada gösterdiğiniz kodu yazmak için bilgileri nereden edindiniz? Ayrıca, set sürümü, karakter takımı ve bu parametrenin çağrılmasının nedenini açıklayabilir misiniz? Varsayılan değerler varsayılan olarak atanmadı mı? Bir soru daha var: org.apache.http.conn.ssl.SSLSocketFactory, değil mi? Bunu temizlediğiniz için teşekkürler –

+0

Bunun, Apress'teki Pro Android uygulamasından geldiğine eminim. Kitap harikaydı, ancak bir uygulamanın bir çok web araması yapması gerektiğinde, http iletişimindeki bölümün pratik tasarım hakkında harika bir tartışması vardı. – Rich

cevap

36

Sana işleyemez neden emin değilim HTTPS . Kendi uygulamalarım için bir yardımcı sınıf yazdım ve sorunsuz bir şekilde HTTPS'ye GET/POST verebiliyorum. Kodu burada yayınlayacağım ve belki de benim kodum ile sizinki arasında fark olup olmadığını görebilirsiniz.

import java.io.IOException; 
import java.io.InputStream; 
import java.io.UnsupportedEncodingException; 
import java.net.HttpURLConnection; 
import java.net.URL; 
import java.net.URLConnection; 

import org.apache.http.HttpResponse; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.client.params.ClientPNames; 
import org.apache.http.client.params.CookiePolicy; 
import org.apache.http.entity.StringEntity; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.params.BasicHttpParams; 
import org.apache.http.params.HttpConnectionParams; 
import org.apache.http.params.HttpParams; 
import org.apache.http.protocol.BasicHttpContext; 
import org.apache.http.protocol.HttpContext; 
import org.apache.http.util.EntityUtils; 
import org.json.JSONObject; 

import android.util.Log; 

public class HttpRequest{ 

    DefaultHttpClient httpClient; 
    HttpContext localContext; 
    private String ret; 

    HttpResponse response = null; 
    HttpPost httpPost = null; 
    HttpGet httpGet = null; 

    public HttpRequest(){ 
     HttpParams myParams = new BasicHttpParams(); 

     HttpConnectionParams.setConnectionTimeout(myParams, 10000); 
     HttpConnectionParams.setSoTimeout(myParams, 10000); 
     httpClient = new DefaultHttpClient(myParams);  
     localContext = new BasicHttpContext();  
    } 

    public void clearCookies() { 
     httpClient.getCookieStore().clear(); 
    } 

    public void abort() { 
     try { 
      if (httpClient != null) { 
       System.out.println("Abort."); 
       httpPost.abort(); 
      } 
     } catch (Exception e) { 
      System.out.println("Your App Name Here" + e); 
     } 
    } 

    public String sendPost(String url, String data) { 
     return sendPost(url, data, null); 
    } 

    public String sendJSONPost(String url, JSONObject data) { 
     return sendPost(url, data.toString(), "application/json"); 
    } 

    public String sendPost(String url, String data, String contentType) { 
     ret = null; 

     httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109); 

     httpPost = new HttpPost(url); 
     response = null; 

     StringEntity tmp = null;   

     Log.d("Your App Name Here", "Setting httpPost headers"); 

     httpPost.setHeader("User-Agent", "SET YOUR USER AGENT STRING HERE"); 
     httpPost.setHeader("Accept", "text/html,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"); 

     if (contentType != null) { 
      httpPost.setHeader("Content-Type", contentType); 
     } else { 
      httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded"); 
     } 

     try { 
      tmp = new StringEntity(data,"UTF-8"); 
     } catch (UnsupportedEncodingException e) { 
      Log.e("Your App Name Here", "HttpUtils : UnsupportedEncodingException : "+e); 
     } 

     httpPost.setEntity(tmp); 

     Log.d("Your App Name Here", url + "?" + data); 

     try { 
      response = httpClient.execute(httpPost,localContext); 

      if (response != null) { 
       ret = EntityUtils.toString(response.getEntity()); 
      } 
     } catch (Exception e) { 
      Log.e("Your App Name Here", "HttpUtils: " + e); 
     } 

     Log.d("Your App Name Here", "Returning value:" + ret); 

     return ret; 
    } 

    public String sendGet(String url) { 
     httpGet = new HttpGet(url); 

     try { 
      response = httpClient.execute(httpGet); 
     } catch (Exception e) { 
      Log.e("Your App Name Here", e.getMessage()); 
     } 

     //int status = response.getStatusLine().getStatusCode(); 

     // we assume that the response body contains the error message 
     try { 
      ret = EntityUtils.toString(response.getEntity()); 
     } catch (IOException e) { 
      Log.e("Your App Name Here", e.getMessage()); 
     } 

     return ret; 
    } 

    public InputStream getHttpStream(String urlString) throws IOException { 
     InputStream in = null; 
     int response = -1; 

     URL url = new URL(urlString); 
     URLConnection conn = url.openConnection(); 

     if (!(conn instanceof HttpURLConnection))      
      throw new IOException("Not an HTTP connection"); 

     try{ 
      HttpURLConnection httpConn = (HttpURLConnection) conn; 
      httpConn.setAllowUserInteraction(false); 
      httpConn.setInstanceFollowRedirects(true); 
      httpConn.setRequestMethod("GET"); 
      httpConn.connect(); 

      response = httpConn.getResponseCode();     

      if (response == HttpURLConnection.HTTP_OK) { 
       in = httpConn.getInputStream();         
      }      
     } catch (Exception e) { 
      throw new IOException("Error connecting");    
     } // end try-catch 

     return in;  
    } 
} 
+0

Bunun için teşekkürler. HttpClient nesnesini oluşturmak için kendi kodumda bir hata oluşturdum (yukarıda kaydedilmiş) – Rich

+1

@MattC, Ben açıkça "Https" veya Port 443'ü kullanmayı tanımladığınız yeri görmüyorum ... bir şey özlüyorum mu? Bu normal bir HTTP bağlantısı gibi görünüyor .. – Cody

+0

@DoctorOreo Bu koda baktığımdan çok uzun zaman geçti. HTTPS'yi doğru bir şekilde ele aldığını hatırlıyorum, ancak o zamandan beri çerçeve çok değişti, o yüzden geri dönüp doğrulamak zorunda kaldım. Üzgünüm daha fazla yardım edemedim. – MattC

1

Bazı yöntemler kullanımdan kaldırıldıkça, bu şekilde olmamalı mı?

private DefaultHttpClient createHttpClient() { 
    HttpParams params = new BasicHttpParams(); 

    HttpConnectionParams.setConnectionTimeout(params, 10000); 
    HttpConnectionParams.setSoTimeout(params, 10000); 
    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 
    HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET); 
    HttpProtocolParams.setUseExpectContinue(params, true); 

    SchemeRegistry schReg = new SchemeRegistry(); 
    schReg.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory())); 
    schReg.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory())); 
    ClientConnectionManager conMgr = new PoolingClientConnectionManager(schReg); 

    return new DefaultHttpClient(conMgr, params); 
    } 

HttpVersion gibi başka bir şeyi değiştirmeli miyim?

+1

Evet. Bu iki yıl önce yayınlandı, ancak bu günlerde AndroidHttpClient.newInstance aslında aynı şeyi yapıyor – Rich

+0

Evet bu Android çalışmıyor – JPM