6

Вопрос по android – Запрос веб-служб Exchange 2007/2010 с помощью SOAP + XML через HTTPS в Android

Я использовал следующий код C # от Microsoft, чтобы запросить EWS 2010MSDN ссылка и это сработало. Мне нужно такое же решение для Android.

Я пытался использовать следующий код, но это не помогает

    DefaultHttpClient client = new HttpsClient(
                MyActivity.this);

        requestBytes = myXMLStringRequest.getBytes("UTF-8");

        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-Type", "text/xml;utf-8");
        if (requestBytes != null) {
            httpPost.setHeader("Content-length",
                    String.valueOf(requestBytes.length));
            Log.d(TAG, "content length: " + requestBytes.length);
        }

        client.getCredentialsProvider().setCredentials(
                new AuthScope(url, 443),
                new UsernamePasswordCredentials(userName,
                        password));
        Log.d(TAG, "Begin request");
        HttpResponse response = client.execute(httpPost);
        Log.d(TAG, "status Line: " + response.getStatusLine().toString());

Вот мой xml запрос

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns="http://schemas.microsoft.com/exchange/services/2006/messages" 
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"> 
<soap:Body>
<GetFolder xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"                xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">   
<FolderShape>     
    <t:BaseShape>Default</t:BaseShape>  
</FolderShape>    
<FolderIds>      
    <t:DistinguishedFolderId Id="inbox"/>     
    <t:DistinguishedFolderId Id="deleteditems"/>  
</FolderIds> 
</GetFolder>

Я также использую пользовательский HttpsClient с хранилищем ключей.

public class HttpsClient extends DefaultHttpClient {
private final Context context;

public HttpsClient(final Context context) {
    super();
    this.context = context;
}

/**
 * The method used to create client connection manager
 */
@Override
protected ClientConnectionManager createClientConnectionManager() {
    final SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 8080));

    // Register for port 443 our SSLSocketFactory with our keystore
    // to the ConnectionManager
    registry.register(new Scheme("https", newSslSocketFactory(), 8443));
    return new SingleClientConnManager(getParams(), registry);
}

private SSLSocketFactory newSslSocketFactory() {
    try {
        // Get an instance of the Bouncy Castle KeyStore format
        final KeyStore trusted = KeyStore.getInstance("BKS");
        // Get the raw resource, which contains the keystore with
        // your trusted certificates (root and any intermediate certs)
        final InputStream inputStream = context.getResources().openRawResource(R.raw.parkgroup_ws_client);
        try {
            // Initialize the keystore with the provided truste
            // certificates
            // Also provide the password of the keystore
            trusted.load(inputStream, "myKeyStorePassword".toCharArray());
        } finally {
            inputStream.close();
        }
        // Pass the keystore to the SSLSocketFactory. The factory is
        // responsible
        // for the verification of the server certificate.
        final SSLSocketFactory ssf = new SSLSocketFactory(trusted);
        // Hostname verification from certificate
        // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        return ssf;
    } catch (Exception e) {
        Log.e("MYTAG", e.getMessage());
        throw new AssertionError(e);
    }
}

@Override
protected HttpParams createHttpParams() {
    final HttpParams httpParams = super.createHttpParams();
    httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 1000);
    httpParams.setParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false);
    return httpParams;
}

}

Но это всегда показывает & quot;connect timeout& Quot; и ничего не отвечает
Пожалуйста, скажите мне, где моя проблема? Любой пример поможет. Заранее спасибо!

  • Поддерживает ли ваш сервер протокол TLS? Существует известная ошибка в Android, что он не может подключиться к некоторым серверам, на которых не включен TLS.

    от Akash Kava
  • Да, это так. Я не знаю, где моя проблема, это всегда тайм-аут

    от R4j
  • 4

    Большое спасибо Николаю Еленкову!

    Наконец-то я нашел решение. Я перехожу по этой ссылке:Использование пользовательского сертификата Trust Store на Android

    Во-первых, я используюDefaultHttpClient вместоHttpClient (методcreateHttpClientWithDefaultSocketFactory() должно бытьreturn DefaultHttpClient):

    private DefaultHttpClient createHttpClientWithDefaultSocketFactory(
            KeyStore keyStore, KeyStore trustStore) {
        try {
            SSLSocketFactory sslSocketFactory = SSLSocketFactory
                    .getSocketFactory();
            if (keyStore != null && trustStore != null) {
                sslSocketFactory = new SSLSocketFactory(keyStore,
                        KEYSTORE_PASSWORD, trustStore);
            } else if (trustStore != null) {
                sslSocketFactory = new SSLSocketFactory(trustStore);
            }
    
            return createHttpClient(sslSocketFactory);
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(e);
        }
    }
    

    Потом добавляюCredentialsProvider для аутентификации.

        DefaultHttpClient client = createHttpClientWithDefaultSocketFactory(
                    keyStore, trustStore);
            HttpPost httpPost = new HttpPost(SERVER_AUTH_URL);
            httpPost.setHeader("Content-type", "text/xml;utf-8");
    
            StringEntity se = new StringEntity(builder.toString(), "UTF8");
            se.setContentType("text/xml");
            httpPost.setEntity(se);
            CredentialsProvider credProvider = new BasicCredentialsProvider();
    
            credProvider.setCredentials(new AuthScope(URL,
                    443), new UsernamePasswordCredentials(USERNAME, password));
    
            // This will exclude the NTLM authentication scheme
    
            client.setCredentialsProvider(credProvider);
            HttpResponse response = client.execute(httpPost);
    

    Теперь это может хорошо работать!