Request Exchange Web Services 2007/2010 with SOAP+XML over HTTPS in Android
android, exchangewebservices
Solution
Many thanks to Nikolay Elenkov!
Finally, I found the solution. I follow this link: Using a Custom Certificate Trust Store on Android
First, I use `DefaultHttpClient` instead of `HttpClient` (the method `createHttpClientWithDefaultSocketFactory()` should be `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);
}
}
Then I add `CredentialsProvider` for authentication.
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);
Now, it can work well!
Problem
I used the following C# code from Microsoft to request EWS 2010 MSDN link and it worked. I need the same solution for android. I tried to use the following code but it does not help ``` 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()); ``` Here is my xml request ``` <?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> ``` I also use custom HttpsClient with keystore. ``` 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; } ``` } But it always show "connect timeout" and does not response anything Please tell me where is my problem? Any example would be help. Thanks in advance!