2010-02-12 26 views
37

Mam dość podstawową klasę pomocniczą, której używam do robienia wszystkich moich rzeczy Get/Post Http. Używam HttpGet, HttpPost i HttpClient z biblioteki org.apache.http. Wszystkie moje rzeczy działają dobrze przez HTTP, ale gdy tylko spróbowałem skorzystać z usługi działającej na HTTPS, otrzymuję wyjątek ClientProtocolException podczas wykonywania żądania. Jedynym komunikatem w tym wyjątku jest "Serwer nie odpowiedział prawidłową odpowiedzią HTTP".Bezpieczny post HTTP w Androidzie

Aby przetestować, wysłałem dokładnie tę samą ładowność z przeglądarki przy użyciu prostego formularza HTML i Fiddler2 przy użyciu RequestBuilder. Wysłałem nieprawidłowe i puste ładunki, a nawet wysłałem wszystkie powyższe za pomocą nagłówków i bez nagłówków, aby sprawdzić, czy coś jest fajne w sposobie budowania żądania przez obiekty.

Wszystko, czego używałem w testach, daje mi prawidłową odpowiedź HTTP o statusie 200. Usługa daje mi strukturę opisującą błąd, jeśli dam mu coś innego niż to, czego oczekuje.

Czy jest coś szczególnego, co muszę dodać do obiektów HttpPost lub HttpClient, aby powiedzieć, że używa HTTPS? Czy muszę wyraźnie powiedzieć, aby użyć innego portu?

EDIT:

I rzeczywiście zarejestrowany niewłaściwego gniazda fabrykę komunikacji https. Oto aktualizowane sposób, że mogę używać do tworzenia mojego httpclient obiekt z prawidłowym fabryki gniazda na wszelki wypadek ktoś szuka tego rodzaju problemów w przyszłości:

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

Witam, bogaty, Dzięki za Twój wpis, jest to jedyna rzecz o https na Androidzie zwrócona przez google. Skąd otrzymałeś informację o napisaniu kodu, który tutaj pokazałeś? Czy mógłbyś również wyjaśnić powód wywołania wersji set, charset i tego parametru? Czy domyślnie nie są przypisane wartości normalne? Jeszcze jedno pytanie: importujesz plik org.apache.http.conn.ssl.SSLSocketFactory, prawda? Dzięki za wyczyszczenie tego –

+0

Jestem prawie pewien, że pochodzi z książki Pro Android na temat Apress. Książka nie była świetna, ale rozdział o komunikacji http miał świetną dyskusję na temat praktycznego projektowania, gdy aplikacja musi wykonywać wiele połączeń internetowych. – Rich

Odpowiedz

36

Nie jestem pewien, dlaczego nie można obsługiwać HTTPS . Napisałem klasę helperów dla własnych aplikacji i mogę bez problemu uzyskać GET/POST do HTTPS. Opublikuję kod tutaj i być może zobaczysz, czy są różnice między moim kodem a twoim.

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

dzięki za to. Miałem błąd w moim własnym kodzie do tworzenia mojego obiektu HttpClient (zamieszczonego powyżej) – Rich

+1

@MattC, nie widzę, gdzie wyraźnie określasz użycie 'Https' lub Port 443 ... czy czegoś brakuje? Wygląda to na normalne połączenie HTTP. – Cody

+0

@DoctorOreo Minęło dużo czasu odkąd przyjrzałem się temu kodowi. Pamiętam, że poprawnie obsługuje HTTPS, ale od tego czasu ramy znacznie się zmieniły, więc musiałem wrócić i zweryfikować. Przepraszam, że nie mogę pomóc. – MattC

1

Ponieważ niektóre metody są przestarzałe, czy nie powinno tak być?

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); 
    } 

Czy powinienem zmienić cokolwiek innego, np. HttpVersion?

+1

Tak. Ta wiadomość została opublikowana ponad dwa lata temu, ale obecnie AndroidHttpClient.newInstance robi dokładnie to samo. – Rich

+0

Tak, to nie działa na Androidzie – JPM