4 votes

Connexion https Android

J'ai une application qui se connecte à un service web qui utilise un certificat Entrust valide. La seule différence est qu'il s'agit d'un SSL de type "wildcard".

Le problème est le suivant : Je reçois un

ERROR/NoHttpResponseException(5195): org.apache.http.NoHttpResponseException: The target server failed to respond

quand je suis en 3G. Quand je suis en WIFI, ça marche, quand je suis sur le simulateur, ça marche, quand je fais un tethering sur le simulateur via mon téléphone 3G, ça marche. Mais l'application sur mon téléphone depuis la 3G ne fonctionne pas du tout. Testé sur un HTC Legend CM7.0.3(2.3.3) et Nexus S 2.3.3 sur 2 réseaux différents (Virgin Mobile Canada et Fido).

J'ai un dump PCAP de mon appareil qui montre quelques erreurs, mais je ne le comprends pas vraiment.

Numéro d'accusé de réception : TCP cassé. Le champ d'accusé de réception est non nul alors que le drapeau ACK n'est pas activé.

J'ai essayé le correctif sur ce question ce question aussi. Je ne sais pas où aller.

A propos, le service web fonctionne avec le navigateur sur 3G.

Nous utilisons également l'authentification de base avec HttpRequestInterceptor.

Je pense que c'est tout ce que je peux donner comme détails. Si vous avez besoin de quelque chose d'autre, n'hésitez pas à me le demander.

Ce site question est aussi lié, j'ai essayé les deux solutions, aucune ne fonctionne.

Modifier

Je commence à penser que cela conviendrait mieux à serverfault.com.

C'est la décharge fichier et la capture d'écran

PCAP

Edit 2

Voici le code que j'utilise pour me connecter au service web en question.

protected HttpEntity sendData(List<NameValuePair> pairs, String method)
            throws ClientProtocolException, IOException,
            AuthenticationException {

        pairs.add(new BasicNameValuePair(KEY_SECURITY, KEY));
        pairs.add(new BasicNameValuePair(LANG_KEY, lang));
        pairs.add(new BasicNameValuePair(OS_KEY, OS));
        pairs.add(new BasicNameValuePair(MODEL_KEY, model));
        pairs.add(new BasicNameValuePair(CARRIER_KEY, carrier));

        DefaultHttpClient client = getClient();

        HttpPost post = new HttpPost();
        try {
            post.setHeader("Content-Type", "application/x-www-form-urlencoded");
            post.setEntity(new UrlEncodedFormEntity(pairs));
        } catch (UnsupportedEncodingException e1) {
            Log.e("UnsupportedEncodingException", e1.toString());
        }

        URI uri = URI.create(method);

        post.setURI(uri);

        client.addRequestInterceptor(preemptiveAuth, 0);

        HttpHost target = new HttpHost(host, port, protocol);
        HttpContext httpContext = new BasicHttpContext();

        HttpResponse response = client.execute(target, post, httpContext);
        int statusCode = response.getStatusLine().getStatusCode();

        if (statusCode == 401) {
            throw new AuthenticationException("Invalid username or password");
        }

        return response.getEntity();
    }

2voto

Michael B. Points 2912

Nous avons finalement trouvé le problème. Ce n'était pas lié au code.

C'est le reverse DNS qui a fait défaut. Comme je n'ai reçu aucune réponse du DNS inverse, ma session apache/ssl a été fermée prématurément.

En utilisant le DNS de Google sur un appareil enraciné, cela a fonctionné.

La seule chose qui reste à faire maintenant est de réparer notre reverse DNS.

Voici une solution de contournement : http://code.google.com/p/Android/issues/detail?id=13117#c14

Appelez cette méthode sur votre instance DefaultHttpClient ou AndroidHttpClient. Elle empêchera la recherche DNS inverse d'être effectuée.

private void workAroundReverseDnsBugInHoneycombAndEarlier(HttpClient client) {
    // Android had a bug where HTTPS made reverse DNS lookups (fixed in Ice Cream Sandwich) 
    // http://code.google.com/p/android/issues/detail?id=13117
    SocketFactory socketFactory = new LayeredSocketFactory() {
        SSLSocketFactory delegate = SSLSocketFactory.getSocketFactory();
        @Override public Socket createSocket() throws IOException {
            return delegate.createSocket();
        }
        @Override public Socket connectSocket(Socket sock, String host, int port,
                InetAddress localAddress, int localPort, HttpParams params) throws IOException {
            return delegate.connectSocket(sock, host, port, localAddress, localPort, params);
        }
        @Override public boolean isSecure(Socket sock) throws IllegalArgumentException {
            return delegate.isSecure(sock);
        }
        @Override public Socket createSocket(Socket socket, String host, int port,
                boolean autoClose) throws IOException {
            injectHostname(socket, host);
            return delegate.createSocket(socket, host, port, autoClose);
        }
        private void injectHostname(Socket socket, String host) {
            try {
                Field field = InetAddress.class.getDeclaredField("hostName");
                field.setAccessible(true);
                field.set(socket.getInetAddress(), host);
            } catch (Exception ignored) {
            }
        }
    };
    client.getConnectionManager().getSchemeRegistry()
            .register(new Scheme("https", socketFactory, 443));
}

1voto

Nicklas A. Points 2979

Avez-vous essayé la solution mentionnée dans HttpClient sur Android : NoHttpResponseException à travers l'UMTS/3G ?

Copie ci-dessous


Je me suis enfin débarrassé de ce problème : simplement un en-tête HTTP qui était mal géré par un serveur squid sur la route :

Attendez : 100-Continue

Il semble être présent par défaut avec DefaultHttpClient sur Android SDK. Pour résoudre ce problème, ajoutez simplement ceci dans votre code :

  HttpProtocolParams.setUseExpectContinue(httpClient.getParams(), false);

-1voto

himanshu Points 99
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();

nameValuePairs.add(new BasicNameValuePair("year","1980"));

//http post

try{

        HttpClient httpclient = new DefaultHttpClient();

        HttpPost httppost = new HttpPost("http://example.com/getAllPeopleBornAfter.php");

        httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        HttpResponse response = httpclient.execute(httppost);
        HttpEntity entity = response.getEntity();

InputStream is = entity.getContent();

}catch(Exception e){

        Log.e("log_tag", "Error in http connection "+e.toString());

}

//convert response to string

try{

BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);

        StringBuilder sb = new StringBuilder();

String line = null;

while ((line = reader.readLine()) != null) {

                sb.append(line + "n");

}

        is.close();

       result=sb.toString();

}catch(Exception e){

        Log.e("log_tag", "Error converting result "+e.toString());

}

référez-vous à ce code pour la connexion http

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X