web-dev-qa-db-ja.com

セキュアHTTPポストAndroid

すべてのHttp Get/Postを行うために使用している非常に基本的なヘルパークラスがあります。 org.Apache.httpライブラリのHttpGet、HttpPost、およびHttpClientを使用しています。すべてのものはHTTPで正常に機能しますが、HTTPSで機能するサービスを利用しようとすると、リクエストの実行時にClientProtocolExceptionが発生します。例外の唯一のメッセージは、「サーバーは有効なHTTP応答で応答できませんでした」です。

テストするために、単純なhtmlフォームを使用してブラウザーからまったく同じペイロードを送信し、RequestBuilderを使用してFiddler2を送信しました。無効で空のペイロードを送信し、ヘッダーの有無にかかわらず上記のすべてを送信して、オブジェクトがリクエストを作成する方法について何か面白いことがあるかどうかを確認しました。

テストで使用したものはすべて、有効な200ステータスのHTTP応答を提供します。このサービスは、期待するもの以外の何かを指定した場合、エラーを説明する構造を提供します。

HTTPSを使用するように通知するためにHttpPostまたはHttpClientオブジェクトに追加する必要がある特別なものはありますか?別のポートを使用するように明示的に指示する必要がありますか?

編集:

実際、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);
}
38
Rich

HTTPSを処理できない理由はわかりません。私は自分のアプリケーションのヘルパークラスを作成し、問題なくHTTPSにGET/POSTできます。ここにコードを投稿します。おそらく、私のコードとあなたのコードに違いがあるかどうかを確認できます。

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;     
    }
}
38
MattC

一部のメソッドは廃止されているため、このようにすべきではありませんか?

  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のような他のものを変更する必要がありますか?

1
Miquel