web-dev-qa-db-fra.com

org.Apache.http.client.ClientProtocolException

J'ai créé une Android qui utilise un certificat X509 (qui se trouve dans le dossier res/raw/mykeystore.bks) pour me connecter au serveur distant qui répond sur le port 9006.

le serveur me demande un identifiant (nom d'utilisateur, mot de passe).

lorsque je crée un HTTPGet, j'ai l'exception suivante: org.Apache.http.client.ClientProtocolException

Voici ma mise en œuvre:

L'activité principale:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button b= (Button) findViewById(R.id.button1);
    b.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {               
             CredentialsProvider credProvider = new BasicCredentialsProvider();
                credProvider.setCredentials(new AuthScope(AuthScope.ANY_Host, AuthScope.ANY_PORT),
                    new UsernamePasswordCredentials("rat#1", "rat"));
            HttpClient client = new MyHttpClient(getApplicationContext());
               ((AbstractHttpClient) client).setCredentialsProvider(credProvider);

               //final String url = "https://211.92.106.38:9006/KPIRest/testKpi/6";
               final String url = "https://211.92.106.38/KPIRest/testKpi/6";
               HttpGet httpGet = new HttpGet(url);

               try {
                HttpResponse response = client.execute(httpGet);
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    });

Classe de client personnalisée:

public class MyHttpClient extends DefaultHttpClient {

final Context context;

public MyHttpClient(Context context) {
    this.context = context;
}

@Override
protected ClientConnectionManager createClientConnectionManager() {

        KeyStore trustStore = null;
            trustStore = KeyStore.getInstance("BKS");

        InputStream in = context.getResources().openRawResource(R.raw.mykeystore);
        try {
            // Initialize the keystore with the provided trusted certificates
            // Also provide the password of the keystore
            trustStore.load(in, "root01".toCharArray());
        } 
        } finally {

                in.close();

        }

        SSLSocketFactory sf=null;

            sf = new MySSLSocketFactory(trustStore);

        sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_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, 9006));
    return new SingleClientConnManager(params, registry);
}
}

Ma classe SSLSoketFactory personnalisée:

public class MySSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");

public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
    super(truststore);

    TrustManager tm = new X509TrustManager() {
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    };

    sslContext.init(null, new TrustManager[] { tm }, null);
}

@Override
public Socket createSocket(Socket socket, String Host, int port, boolean autoClose) throws IOException, UnknownHostException {
    return sslContext.getSocketFactory().createSocket(socket, Host, port, autoClose);
}

@Override
public Socket createSocket() throws IOException {
    return sslContext.getSocketFactory().createSocket();
}
}

quel est le problème dans ma candidature? Qu'est-ce qui cause cette exception?

Merci à tous!

ÉDITER:

Je cherchais mieux l'exception:

cause = org.Apache.http.auth.MalformedChallengeException: le défi d'authentification est vide.

EDIT 2:

J'ai essayé d'utiliser cette implémentation sans aucune différence, j'ai la même exception!

EDIT 3: j'ai remplacé

 CredentialsProvider credProvider = new BasicCredentialsProvider();
                credProvider.setCredentials(new AuthScope(AuthScope.ANY_Host, AuthScope.ANY_PORT),
                    new UsernamePasswordCredentials("rat#1", "rat"));

client) .setCredentialsProvider (credProvider);

avec l'authentification de base httpclient, en ajoutant l'en-tête Authorization à httpGet:

  httpGet.addHeader("Authorization", "Basic "+Base64.encodeToString("rat#1:rat".getBytes(),Base64.DEFAULT));

maintenant le serveur m'envoie ce message:

HTTP/1.1 400 Bad Request 
11
Marco

le problème était l'en-tête d'autorisation.

Nous devons utiliser:

httpGet.addHeader("Authorization", "Basic "+Base64.encodeToString("rat#1:rat".getBytes(),Base64.NO_WRAP));

Au lieu de:

httpGet.addHeader("Authorization", "Basic "+Base64.encodeToString("rat#1:rat".getBytes(),Base64.DEFAULT));

car le paramètre DEFAULT ajoute un terminateur de ligne "CR" à la fin de la chaîne et il n'est pas correct si vous l'utilisez cet en-tête.

13
Marco