Безопасный HTTP-пост в Android
У меня есть довольно простой вспомогательный класс, который я использую для всего, что связано с Http Get/Post. Я использую HttpGet, HttpPost и HttpClient из библиотеки org.apache.http. Все мои вещи отлично работают по HTTP, но как только я попытался использовать сервис, работающий по HTTPS, я получаю исключение ClientProtocolException при выполнении запроса. Единственное сообщение в исключении: "Серверу не удалось ответить правильным HTTP-ответом".
Чтобы проверить, я отправил ту же самую полезную нагрузку из браузера, используя простую HTML-форму, и Fiddler2, используя RequestBuilder. Я отправил недопустимые и пустые полезные данные и даже отправил все вышеперечисленное с заголовками и без них, чтобы узнать, было ли что-то необычное в том, как объекты создавали запрос.
Все, что я использовал в тестировании, дает мне действительный HTTP-ответ 200 статуса. Служба просто дает мне структуру, описывающую ошибку, если я даю ей что-то, отличное от ожидаемого.
Есть ли что-то особенное, что мне нужно добавить в объект (ы) HttpPost или HttpClient, чтобы сказать ему использовать HTTPS? Должен ли я явно указать ему использовать другой порт?
РЕДАКТИРОВАТЬ:
Я действительно зарегистрировал неправильную фабрику сокетов для связи https. Вот обновленный метод, который я использую для создания моего объекта HttpClient с правильной фабрикой сокетов на случай, если кто-то будет искать такую проблему в будущем:
private HttpClient createHttpClient()
{
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);
return new DefaultHttpClient(conMgr, params);
}
2 ответа
Я не уверен, почему вы не можете справиться с HTTPS. Я написал вспомогательный класс для своих собственных приложений, и я могу без проблем получать / отправлять по HTTPS. Я опубликую код здесь, и, возможно, вы увидите, есть ли различия между моим и вашим кодом.
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import android.util.Log;
public class HttpRequest{
DefaultHttpClient httpClient;
HttpContext localContext;
private String ret;
HttpResponse response = null;
HttpPost httpPost = null;
HttpGet httpGet = null;
public HttpRequest(){
HttpParams myParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(myParams, 10000);
HttpConnectionParams.setSoTimeout(myParams, 10000);
httpClient = new DefaultHttpClient(myParams);
localContext = new BasicHttpContext();
}
public void clearCookies() {
httpClient.getCookieStore().clear();
}
public void abort() {
try {
if (httpClient != null) {
System.out.println("Abort.");
httpPost.abort();
}
} catch (Exception e) {
System.out.println("Your App Name Here" + e);
}
}
public String sendPost(String url, String data) {
return sendPost(url, data, null);
}
public String sendJSONPost(String url, JSONObject data) {
return sendPost(url, data.toString(), "application/json");
}
public String sendPost(String url, String data, String contentType) {
ret = null;
httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109);
httpPost = new HttpPost(url);
response = null;
StringEntity tmp = null;
Log.d("Your App Name Here", "Setting httpPost headers");
httpPost.setHeader("User-Agent", "SET YOUR USER AGENT STRING HERE");
httpPost.setHeader("Accept", "text/html,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
if (contentType != null) {
httpPost.setHeader("Content-Type", contentType);
} else {
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
}
try {
tmp = new StringEntity(data,"UTF-8");
} catch (UnsupportedEncodingException e) {
Log.e("Your App Name Here", "HttpUtils : UnsupportedEncodingException : "+e);
}
httpPost.setEntity(tmp);
Log.d("Your App Name Here", url + "?" + data);
try {
response = httpClient.execute(httpPost,localContext);
if (response != null) {
ret = EntityUtils.toString(response.getEntity());
}
} catch (Exception e) {
Log.e("Your App Name Here", "HttpUtils: " + e);
}
Log.d("Your App Name Here", "Returning value:" + ret);
return ret;
}
public String sendGet(String url) {
httpGet = new HttpGet(url);
try {
response = httpClient.execute(httpGet);
} catch (Exception e) {
Log.e("Your App Name Here", e.getMessage());
}
//int status = response.getStatusLine().getStatusCode();
// we assume that the response body contains the error message
try {
ret = EntityUtils.toString(response.getEntity());
} catch (IOException e) {
Log.e("Your App Name Here", e.getMessage());
}
return ret;
}
public InputStream getHttpStream(String urlString) throws IOException {
InputStream in = null;
int response = -1;
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
if (!(conn instanceof HttpURLConnection))
throw new IOException("Not an HTTP connection");
try{
HttpURLConnection httpConn = (HttpURLConnection) conn;
httpConn.setAllowUserInteraction(false);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("GET");
httpConn.connect();
response = httpConn.getResponseCode();
if (response == HttpURLConnection.HTTP_OK) {
in = httpConn.getInputStream();
}
} catch (Exception e) {
throw new IOException("Error connecting");
} // end try-catch
return in;
}
}
Поскольку некоторые из методов устарели, не должно ли быть так?
private DefaultHttpClient createHttpClient() {
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 10000);
HttpConnectionParams.setSoTimeout(params, 10000);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
schReg.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));
ClientConnectionManager conMgr = new PoolingClientConnectionManager(schReg);
return new DefaultHttpClient(conMgr, params);
}
Должен ли я изменить что-нибудь еще, как HttpVersion?