HttpPost работает в проекте Java, а не в Android

Я написал некоторый код для моего устройства Android для входа на веб-сайт через https и проанализировать некоторые данные из полученных страниц. HttpGet происходит сначала, чтобы получить некоторую информацию, необходимую для входа в систему, а затем HttpPost сделать фактический процесс входа в систему.

Приведенный ниже код прекрасно работает в Java-проекте в Eclipse, который содержит следующие файлы Jar в пути сборки: httpcore-4.1-beta2.jar, httpclient-4.1-alpha2.jar, httpmime-4.1-alpha2.jar, commons-logging-1.1.1.jar,

public static MyBean gatherData(String username, String password) {
    MyBean myBean = new MyBean();
    try {
        HttpResponse response = doHttpGet(URL_PAGE_LOGIN, null, null);
        System.out.println("Got login page");
        String content = EntityUtils.toString(response.getEntity());
        String token = ContentParser.getToken(content);
        String cookie = getCookie(response);
        System.out.println("Performing login");
        System.out.println("token = "+token +" || cookie = "+cookie);
        response = doLoginPost(username,password,cookie, token);
        int respCode = response.getStatusLine().getStatusCode();
        if (respCode != 302) {
            System.out.println("ERROR: not a 302 redirect!: code is \""+ respCode+"\"");
            if (respCode == 200) {
                System.out.println(getHeaders(response));
                System.out.println(EntityUtils.toString(response.getEntity()).substring(0, 500));
            }
        } else {
            System.out.println("Logged in OK, loading account home");
            // redirect handler and rest of parse removed
        }
    }catch (Exception e) {
        System.out.println("ERROR in gatherdata: "+e.toString());
        e.printStackTrace();
    }
    return myBean;
}
private static HttpResponse doHttpGet(String url, String cookie, String referrer) {
    try {
        HttpClient client = new DefaultHttpClient();
        client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
        client.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8");
        HttpGet httpGet = new HttpGet(url);
        httpGet.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
        httpGet.setHeader(HEADER_USER_AGENT,HEADER_USER_AGENT_VALUE);
        if (referrer != null && !referrer.equals("")) httpGet.setHeader(HEADER_REFERER,referrer);
        if (cookie != null && !cookie.equals("")) httpGet.setHeader(HEADER_COOKIE,cookie);
        return client.execute(httpGet);
    } catch (Exception e) {
        e.printStackTrace();
        throw new ConnectException("Failed to read content from response");
    }
}
private static HttpResponse doLoginPost(String username, String password, String cookie, String token) throws ClientProtocolException, IOException {
    try {
        HttpClient client = new DefaultHttpClient();
        client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
        client.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8");
        HttpPost post = new HttpPost(URL_LOGIN_SUBMIT);
        post.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
        post.setHeader(HEADER_USER_AGENT,HEADER_USER_AGENT_VALUE);
        post.setHeader(HEADER_REFERER, URL_PAGE_LOGIN);
        post.setHeader(HEADER_COOKIE, cookie);
        post.setHeader("Content-Type","application/x-www-form-urlencoded");
        List<NameValuePair> formParams = new ArrayList<NameValuePair>();
        formParams.add(new BasicNameValuePair("org.apache.struts.taglib.html.TOKEN", token));
        formParams.add(new BasicNameValuePair("showLogin", "true"));
        formParams.add(new BasicNameValuePair("upgrade", ""));
        formParams.add(new BasicNameValuePair("username", username));
        formParams.add(new BasicNameValuePair("password", password));
        formParams.add(new BasicNameValuePair("submit", "Secure+Log+in"));
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams,HTTP.UTF_8);
        post.setEntity(entity);
        return client.execute(post);
    } catch (Exception e) {
        e.printStackTrace();
        throw new ConnectException("ERROR in doLoginPost(): "+e.getMessage());
    }
}

Сервер (который не находится под моим контролем) возвращает перенаправление 302 при успешном входе в систему и 200 при сбое и повторную загрузку страницы входа. При запуске с указанными выше файлами Jar я получаю перенаправление 302, однако, если я запускаю точно такой же код из проекта Android с файлом Jar Android 1.6 в пути сборки, я получаю ответ 200 от сервера. Я получаю тот же ответ 200 при запуске кода на моем устройстве 2.2.

У моего андроид-приложения есть интернет-разрешения, и HttpGet работает нормально. Я предполагаю, что проблема заключается в том факте, что HttpPost (или какой-то другой класс) существенно отличается между версией Android Jar и более новыми версиями Apache.

Я попытался добавить библиотеки Apache в путь сборки проекта Android, но из-за дублирующихся классов я получаю сообщения вроде: INFO/dalvikvm(390): DexOpt: not resolving ambiguous class 'Lorg/apache/http/impl/client/DefaultHttpClient;' в журнале. Я также пытался использовать MultipartEntity вместо UrlEncodedFormEntity но я получаю тот же 200 результат.

Итак, у меня есть несколько вопросов:
- Могу ли я заставить код, работающий под Android, использовать более новые библиотеки Apache по сравнению с версиями Android?
- Если нет, у кого-нибудь есть идеи, как я могу изменить свой код, чтобы он работал с Android Jar?
- Есть ли другие, совершенно разные подходы к созданию HttpPost в Android?
- Есть еще идеи?

Я прочитал много постов и кода, но никуда не денусь. Я застрял на этом пару дней, и я не знаю, как заставить это работать, так что я попробую что-нибудь на этом этапе. Заранее спасибо.

4 ответа

Решение

Теперь я разочаровался в получении HttpClient маршрут, чтобы дать ожидаемый ответ от сервера при запуске на Android. Вместо этого я переписал doPost метод выше, чтобы использовать HttpsURLConnection вместо. Вот новая (рабочая) версия в надежде, что она кому-нибудь пригодится.

private static LoginBean altPost(String username, String password, String cookie, String token){
    LoginBean loginBean = new LoginBean();
    HttpsURLConnection urlc = null;
    OutputStreamWriter out = null;
    DataOutputStream dataout = null;
    BufferedReader in = null;
    try {
        URL url = new URL(URL_LOGIN_SUBMIT);
        urlc = (HttpsURLConnection) url.openConnection();
        urlc.setRequestMethod("POST");
        urlc.setDoOutput(true);
        urlc.setDoInput(true);
        urlc.setUseCaches(false);
        urlc.setAllowUserInteraction(false);
        urlc.setRequestProperty(HEADER_USER_AGENT, HEADER_USER_AGENT_VALUE_FF);
        urlc.setRequestProperty("Cookie", cookie);
        urlc.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
        String output = "org.apache.struts.taglib.html.TOKEN="+ URLEncoder.encode(token, HTTP.UTF_8)
                +"&showLogin=true&upgrade=&username="+ URLEncoder.encode(username, HTTP.UTF_8)
                +"&password="+ URLEncoder.encode(password, HTTP.UTF_8)+"&submit="
                +URLEncoder.encode("Secure+Log+in", HTTP.UTF_8);
        dataout = new DataOutputStream(urlc.getOutputStream());
        // perform POST operation
        dataout.writeBytes(output);
        // get response info
        loginBean.setResponseCode(urlc.getResponseCode());
        // get required headers
        String headerName = null;
        StringBuffer newCookie = new StringBuffer(100);
        String redirectLocation = "";
        for (int i=1; (headerName = urlc.getHeaderField(i)) != null;i++) {
            if (headerName.indexOf(COOKIE_VALUE_SESSION) > -1) {
                if (newCookie.length() > 0) {newCookie.append("; ");}
                newCookie.append(headerName);
            }
            if (headerName.indexOf(COOKIE_VALUE_AUTH) > -1) {
                if (newCookie.length() > 0) {newCookie.append("; ");}
                newCookie.append(headerName);
            }
            if (headerName.indexOf("https://") > -1) {
                redirectLocation = headerName;
            }
        }
        loginBean.setCookie(newCookie.toString());
        loginBean.setRedirectUrl(redirectLocation);

        in = new BufferedReader(new InputStreamReader(urlc.getInputStream()),8096);
        String response;
        // write html to System.out for debug
        while ((response = in.readLine()) != null) {
            System.out.println(response);
        }
        in.close();
    } catch (ProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return loginBean;
}

Я до сих пор понятия не имею, почему HttpClient путь не работал должным образом.

Чтобы избежать столкновений, используйте эту банку для httpclient

HTTPLIB

и этот пост также будет очень полезен

сообщение переполнения стека

Проверьте RedirectHandler, переопределите стандартный и выполните вход в него, у меня были проблемы с этим при переходе на Android...

Возможно ли, что этот сайт обнаруживает пользовательский агент и на самом деле возвращает разные результаты, потому что это Android? Учитывая, что 200 означает успех, почему он должен давать 302 вместо 200? Распечатали ли вы результат, который вы получаете, когда он возвращает 200, и дает ли он какую-либо дополнительную информацию?

Другие вопросы по тегам