我已编写代码从外部服务器下载一些数据。服务器使用自签名证书,需要设置会话cookie和一些POST数据。目前我有以下代码:
private byte[] getResponse(URL url, String postData)
throws IOException, KeyManagementException, CertificateException, KeyStoreException,
NoSuchAlgorithmException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setRequestProperty("User-Agent", userAgent);
urlConnection.setRequestProperty("Cookie", cookie);
urlConnection.setRequestMethod("POST");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setSSLSocketFactory(getSocketFactory());
OutputStream os = urlConnection.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(postData);
writer.flush();
writer.close();
os.close();
try {
urlConnection.connect();
InputStream is = urlConnection.getInputStream();
int len = 0;
while ((len = is.read(buffer)) != -1)
{
baos.write(buffer, 0, len);
}
}
catch(IOException e)
{
throw e;
}
finally {
urlConnection.disconnect();
}
return baos.toByteArray();
}
在冰淇淋三明治及更高级别(API> = 14)一切正常。当我尝试使应用程序在API> = 8上运行时,问题就出现了。现在正在使用GET正确发送请求而没有参数(CAPTCHA)但是当获取实际数据时urlConnection的连接方法失败毫无例外。 getSocketFactory()的代码是:
private SSLSocketFactory getSocketFactory()
throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException,
KeyManagementException
{
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = context.getResources().openRawResource(R.raw.historiapojazdu);
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
return context.getSocketFactory();
}
编辑:我刚刚意识到连接方法显然有效,但它没有跟上响应的重定向,因此输入流始终为空。
答案 0 :(得分:0)
我自己就是这么想的。尽管隐式调用setInstanceFollowRedirects(true),看起来HttpsUrlConnection根本不遵循API 10上的重定向并且由于某种原因而降低。它只是忽略了这个设置。在调用urlConnection.connect()后,我已经使用此代码解决了这个问题:
String redirect = urlConnection.getHeaderField("Location");
if(redirect != null) //truth before ICS
{
urlConnection.disconnect();
urlConnection = (HttpsURLConnection) (new URL(redirect)).openConnection();
urlConnection.setRequestProperty("User-Agent", userAgent);
urlConnection.setRequestProperty("Cookie", cookie);
urlConnection.setRequestMethod("POST");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setSSLSocketFactory(getSocketFactory());
OutputStream os2 = urlConnection.getOutputStream();
BufferedWriter writer2 = new BufferedWriter(
new OutputStreamWriter(os2, "UTF-8"));
writer2.write(postData);
writer2.flush();
writer2.close();
os2.close();
urlConnection.connect();
}