Làm cách nào để thực hiện yêu cầu http bằng cookie trên Android?


121

Tôi muốn thực hiện yêu cầu http tới máy chủ từ xa trong khi xử lý cookie đúng cách (ví dụ: lưu trữ cookie do máy chủ gửi và gửi các cookie đó khi tôi thực hiện các yêu cầu tiếp theo). Sẽ rất tốt nếu bảo quản bất kỳ và tất cả cookie, nhưng thực sự thứ duy nhất tôi quan tâm là cookie phiên.

Với java.net, có vẻ như cách ưa thích để làm điều này là sử dụng java.net.CookieHandler (lớp cơ sở trừu tượng) và java.net.CookieManager (triển khai cụ thể). Android có java.net.CookieHandler, nhưng dường như không có java.net.CookieManager.

Tôi có thể viết mã tất cả bằng tay bằng cách kiểm tra các tiêu đề http, nhưng có vẻ như phải có một cách dễ dàng hơn.

Cách thích hợp để thực hiện yêu cầu http trên Android trong khi vẫn giữ cookie là gì?


Bạn đã thử org.apache.http.cookie chưa?
Jack L.

3
Cũng như một lưu ý hơn hai năm sau: java.net.CookieManagerhiện đã được hỗ trợ trong Android kể từ phiên bản 2.3 (API cấp 9): developer.android.com/reference/java/net/CookieManager.html
Slauma

Câu trả lời:


92

Hóa ra là Google Android cung cấp Apache HttpClient 4.0 và tôi có thể tìm ra cách thực hiện điều đó bằng cách sử dụng ví dụ "Đăng nhập dựa trên biểu mẫu" trong tài liệu HttpClient :

https://github.com/apache/httpcomponents-client/blob/master/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientFormLogin.java


import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

/**
 * A example that demonstrates how HttpClient APIs can be used to perform
 * form-based logon.
 */
public class ClientFormLogin {

    public static void main(String[] args) throws Exception {

        DefaultHttpClient httpclient = new DefaultHttpClient();

        HttpGet httpget = new HttpGet("https://portal.sun.com/portal/dt");

        HttpResponse response = httpclient.execute(httpget);
        HttpEntity entity = response.getEntity();

        System.out.println("Login form get: " + response.getStatusLine());
        if (entity != null) {
            entity.consumeContent();
        }
        System.out.println("Initial set of cookies:");
        List<Cookie> cookies = httpclient.getCookieStore().getCookies();
        if (cookies.isEmpty()) {
            System.out.println("None");
        } else {
            for (int i = 0; i < cookies.size(); i++) {
                System.out.println("- " + cookies.get(i).toString());
            }
        }

        HttpPost httpost = new HttpPost("https://portal.sun.com/amserver/UI/Login?" +
                "org=self_registered_users&" +
                "goto=/portal/dt&" +
                "gotoOnFail=/portal/dt?error=true");

        List <NameValuePair> nvps = new ArrayList <NameValuePair>();
        nvps.add(new BasicNameValuePair("IDToken1", "username"));
        nvps.add(new BasicNameValuePair("IDToken2", "password"));

        httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));

        response = httpclient.execute(httpost);
        entity = response.getEntity();

        System.out.println("Login form get: " + response.getStatusLine());
        if (entity != null) {
            entity.consumeContent();
        }

        System.out.println("Post logon cookies:");
        cookies = httpclient.getCookieStore().getCookies();
        if (cookies.isEmpty()) {
            System.out.println("None");
        } else {
            for (int i = 0; i < cookies.size(); i++) {
                System.out.println("- " + cookies.get(i).toString());
            }
        }

        // When HttpClient instance is no longer needed, 
        // shut down the connection manager to ensure
        // immediate deallocation of all system resources
        httpclient.getConnectionManager().shutdown();        
    }
}

11
tôi có thể biết cách đặt cookie thành Url yêu cầu để kiểm tra phiên xem có hợp lệ hay không?
Praveen

CẢM ƠN BẠN đã giới thiệu cho tôi BasicNameValuePairs. Họ đã giúp tôi.
bhekman

3
Tôi hiểu The method getCookieStore() is undefined for the type HttpClient, Tôi có phải đổi sang List<Cookie> cookies = ((AbstractHttpClient) httpclient).getCookieStore().getCookies();không? Vì nếu tôi làm, nó hoạt động.
Francisco Corrales Morales

@Praveen Hãy xem ở đây để lưu Cookie: stackoverflow.com/a/5989115/2615737
Francisco Corrales Morales

@emmby: mô-đun apache android không được dùng nữa. Vì vậy, ngay bây giờ câu trả lời của anh ấy không hữu ích. Có cách nào khác để làm điều này với HttpURLConnection không?
Milad Faridnia

9

Cookie chỉ là một tiêu đề HTTP khác. Bạn luôn có thể đặt nó trong khi thực hiện cuộc gọi HTTP với thư viện apache hoặc với HTTPUrlConnection. Dù bằng cách nào thì bạn cũng có thể đọc và đặt các cookie HTTP theo cách này.

Bạn có thể đọc bài viết này để biết thêm thông tin.

Tôi có thể chia sẻ sự yên tâm về mã của mình để chứng minh bạn có thể thực hiện nó dễ dàng như thế nào.

public static String getServerResponseByHttpGet(String url, String token) {

        try {
            HttpClient client = new DefaultHttpClient();
            HttpGet get = new HttpGet(url);
            get.setHeader("Cookie", "PHPSESSID=" + token + ";");
            Log.d(TAG, "Try to open => " + url);

            HttpResponse httpResponse = client.execute(get);
            int connectionStatusCode = httpResponse.getStatusLine().getStatusCode();
            Log.d(TAG, "Connection code: " + connectionStatusCode + " for request: " + url);

            HttpEntity entity = httpResponse.getEntity();
            String serverResponse = EntityUtils.toString(entity);
            Log.d(TAG, "Server response for request " + url + " => " + serverResponse);

            if(!isStatusOk(connectionStatusCode))
                return null;

            return serverResponse;

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

Điều này giúp tôi rất nhiều, +1 get.setHeader ("Cookie", "PHPSESSID =" + token + ";"); làm công việc
Oussaki

@Hesam: mô-đun apache android không may không dùng nữa. Vì vậy, ngay bây giờ câu trả lời của anh ấy không hữu ích. Có cách nào khác để làm điều này với HttpURLConnection không?
Milad Faridnia

7

thư viện Apache không còn được dùng nữa , nên đối với những người muốn sử dụng HttpURLConncetion, tôi đã viết lớp này để gửi Yêu cầu Nhận và Đăng với sự trợ giúp của câu trả lời sau:

public class WebService {

static final String COOKIES_HEADER = "Set-Cookie";
static final String COOKIE = "Cookie";

static CookieManager msCookieManager = new CookieManager();

private static int responseCode;

public static String sendPost(String requestURL, String urlParameters) {

    URL url;
    String response = "";
    try {
        url = new URL(requestURL);

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setReadTimeout(15000);
        conn.setConnectTimeout(15000);
        conn.setRequestMethod("POST");

        conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");

        if (msCookieManager.getCookieStore().getCookies().size() > 0) {
            //While joining the Cookies, use ',' or ';' as needed. Most of the server are using ';'
            conn.setRequestProperty(COOKIE ,
                    TextUtils.join(";", msCookieManager.getCookieStore().getCookies()));
        }

        conn.setDoInput(true);
        conn.setDoOutput(true);

        OutputStream os = conn.getOutputStream();
        BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(os, "UTF-8"));

        if (urlParameters != null) {
            writer.write(urlParameters);
        }
        writer.flush();
        writer.close();
        os.close();

        Map<String, List<String>> headerFields = conn.getHeaderFields();
        List<String> cookiesHeader = headerFields.get(COOKIES_HEADER);

        if (cookiesHeader != null) {
            for (String cookie : cookiesHeader) {
                msCookieManager.getCookieStore().add(null, HttpCookie.parse(cookie).get(0));
            }
        }

        setResponseCode(conn.getResponseCode());

        if (getResponseCode() == HttpsURLConnection.HTTP_OK) {

            String line;
            BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            while ((line = br.readLine()) != null) {
                response += line;
            }
        } else {
            response = "";
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    return response;
}


// HTTP GET request
public static String sendGet(String url) throws Exception {

    URL obj = new URL(url);
    HttpURLConnection con = (HttpURLConnection) obj.openConnection();

    // optional default is GET
    con.setRequestMethod("GET");

    //add request header 
    con.setRequestProperty("User-Agent", "Mozilla");
    /*
    * /programming/16150089/how-to-handle-cookies-in-httpurlconnection-using-cookiemanager
    * Get Cookies form cookieManager and load them to connection:
     */
    if (msCookieManager.getCookieStore().getCookies().size() > 0) {
        //While joining the Cookies, use ',' or ';' as needed. Most of the server are using ';'
        con.setRequestProperty(COOKIE ,
                TextUtils.join(";", msCookieManager.getCookieStore().getCookies()));
    }

    /*
    * /programming/16150089/how-to-handle-cookies-in-httpurlconnection-using-cookiemanager
    * Get Cookies form response header and load them to cookieManager:
     */
    Map<String, List<String>> headerFields = con.getHeaderFields();
    List<String> cookiesHeader = headerFields.get(COOKIES_HEADER);
    if (cookiesHeader != null) {
        for (String cookie : cookiesHeader) {
            msCookieManager.getCookieStore().add(null, HttpCookie.parse(cookie).get(0));
        }
    }


    int responseCode = con.getResponseCode();

    BufferedReader in = new BufferedReader(
            new InputStreamReader(con.getInputStream()));
    String inputLine;
    StringBuffer response = new StringBuffer();

    while ((inputLine = in.readLine()) != null) {
        response.append(inputLine);
    }
    in.close();

    return response.toString();
}

public static void setResponseCode(int responseCode) {
    WebService.responseCode = responseCode;
    Log.i("Milad", "responseCode" + responseCode);
}


public static int getResponseCode() {
    return responseCode;
}
}

2
Cô giáo lớp tốt đẹp! Nó đã giúp tôi rất nhiều ! Bây giờ, tôi đã tự hỏi, nếu tôi muốn lưu các cookie cho nó có sẵn nếu người dùng giết ứng dụng và triển khai nó một lần nữa, những gì chính xác tôi nên lưu trữ và nơi (như thế nào)
Ki Jey

1

Tôi không làm việc với google android nhưng tôi nghĩ bạn sẽ thấy không khó để làm việc này. Nếu bạn đọc phần liên quan của hướng dẫn java, bạn sẽ thấy rằng một trình xử lý cookie đã đăng ký nhận các lệnh gọi lại từ mã HTTP.

Vì vậy, nếu không có mặc định (bạn đã kiểm tra xem có CookieHandler.getDefault()thực sự là null hay không?) Thì bạn chỉ cần mở rộng CookieHandler, thực hiện put / get và làm cho nó hoạt động khá tự động. Hãy chắc chắn xem xét truy cập đồng thời và tương tự nếu bạn đi theo tuyến đường đó.

chỉnh sửa: Rõ ràng là bạn phải đặt một phiên bản triển khai tùy chỉnh của mình làm trình xử lý mặc định thông qua CookieHandler.setDefault()để nhận các lệnh gọi lại. Quên đề cập đến điều đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.