6

我使用来自 Microsoft 的以下 C# 代码请求 EWS 2010 MSDN 链接并且它有效。我需要为 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;
}

}

但它总是显示“连接超时”并且没有响应
请告诉我我的问题在哪里?任何例子都会有所帮助。提前致谢!

4

1 回答 1

4

非常感谢 Nikolay Elenkov!

最后,我找到了解决方案。我点击此链接:在 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);

现在,它可以正常工作了!

于 2012-04-12T10:57:13.130 回答