ฉันจะขอ http โดยใช้คุกกี้บน Android ได้อย่างไร?


121

ฉันต้องการส่งคำขอ http ไปยังเซิร์ฟเวอร์ระยะไกลในขณะที่จัดการคุกกี้อย่างถูกต้อง (เช่นจัดเก็บคุกกี้ที่เซิร์ฟเวอร์ส่งมาและส่งคุกกี้เหล่านั้นเมื่อฉันทำการร้องขอในภายหลัง) เป็นการดีที่จะเก็บคุกกี้ใด ๆ และทั้งหมดไว้ แต่สิ่งเดียวที่ฉันสนใจคือคุกกี้เซสชัน

ด้วย java.net ดูเหมือนว่าวิธีที่ต้องการคือใช้ java.net.CookieHandler (คลาสฐานนามธรรม) และ java.net.CookieManager (การนำไปใช้อย่างเป็นรูปธรรม) Android มี java.net.CookieHandler แต่ดูเหมือนว่าจะไม่มี java.net.CookieManager

ฉันสามารถเขียนโค้ดทั้งหมดด้วยมือโดยตรวจสอบส่วนหัว http แต่ดูเหมือนว่าจะต้องมีวิธีที่ง่ายกว่านี้

อะไรคือวิธีที่เหมาะสมในการส่งคำขอ http บน Android ในขณะที่เก็บคุกกี้ไว้


คุณเคยลองorg.apache.http.cookieหรือยัง?
Jack L.

3
เช่นเดียวกับบันทึกมากกว่าสองปีต่อมา: java.net.CookieManagerตอนนี้รองรับ Android ตั้งแต่เวอร์ชัน 2.3 (API ระดับ 9): developer.android.com/reference/java/net/CookieManager.html
Slauma

คำตอบ:


92

ปรากฎว่า Google Android มาพร้อมกับ Apache HttpClient 4.0 และฉันสามารถหาวิธีทำได้โดยใช้ตัวอย่าง "การเข้าสู่ระบบแบบฟอร์ม" ในเอกสาร 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
ฉันขอทราบวิธีตั้งค่าคุกกี้เป็น Request Url เพื่อตรวจสอบเซสชันว่าถูกต้องหรือไม่
ประวีณ

ขอบคุณที่แนะนำ BasicNameValuePairs พวกเขาช่วยฉัน
bhekman

3
ฉันได้รับThe method getCookieStore() is undefined for the type HttpClientฉันต้องเปลี่ยนเป็นList<Cookie> cookies = ((AbstractHttpClient) httpclient).getCookieStore().getCookies();? เพราะถ้าฉันทำมันได้ผล
Francisco Corrales Morales

@Praveen ดูที่นี่เพื่อบันทึกคุกกี้: stackoverflow.com/a/5989115/2615737
Francisco Corrales Morales

@emmby: โชคร้ายที่หุ่นยนต์เลิกใช้โมดูล apache ตอนนี้คำตอบของเขาไม่เป็นประโยชน์มีวิธีอื่นในการดำเนินการกับ HttpURLConnection หรือไม่?
Milad Faridnia

9

คุกกี้เป็นเพียงส่วนหัว HTTP อื่น คุณสามารถตั้งค่าได้ตลอดเวลาขณะทำการโทร HTTP ด้วยไลบรารี apache หรือด้วย HTTPUrlConnection ไม่ว่าจะด้วยวิธีใดคุณจะสามารถอ่านและตั้งค่าคุกกี้ HTTP ได้ในลักษณะนี้

คุณสามารถอ่านบทความนี้เพื่อดูข้อมูลเพิ่มเติม

ฉันสามารถแบ่งปันความสงบของรหัสเพื่อแสดงให้เห็นว่าคุณทำได้ง่ายเพียงใด

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

สิ่งนี้ช่วยฉันได้มาก +1 get.setHeader ("คุกกี้", "PHPSESSID =" + โทเค็น + ";"); ทำงาน
Oussaki

@Hesam: โชคร้ายที่ Android เลิกใช้โมดูล Apache ตอนนี้คำตอบของเขาไม่เป็นประโยชน์มีวิธีอื่นในการดำเนินการกับ HttpURLConnection หรือไม่?
Milad Faridnia

7

เนื่องจากห้องสมุด Apache เลิกใช้งานแล้วสำหรับผู้ที่ต้องการใช้HttpURLConncetionฉันจึงเขียนคลาสนี้เพื่อส่ง Get and Post Request โดยใช้คำตอบนี้ :

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
Nice Class Milad! มันช่วยฉันได้มาก! ตอนนี้ฉันสงสัยว่าถ้าฉันต้องการบันทึกคุกกี้เพื่อให้ใช้งานได้หากผู้ใช้ฆ่าแอปและเปิดใช้งานอีกครั้งฉันควรเก็บอะไรและที่ไหน (อย่างไร)
Ki Jéy

1

ฉันไม่ได้ทำงานกับ google android แต่ฉันคิดว่าคุณจะพบว่ามันไม่ยากที่จะทำให้มันใช้งานได้ หากคุณอ่านบทช่วยสอน java ที่เกี่ยวข้องคุณจะเห็นว่า cookiehandler ที่ลงทะเบียนได้รับการติดต่อกลับจากรหัส HTTP

ดังนั้นหากไม่มีค่าเริ่มต้น (คุณตรวจสอบแล้วหรือยังว่าCookieHandler.getDefault()เป็นโมฆะจริง ๆ หรือไม่) คุณก็สามารถขยาย CookieHandler ใช้ put / get และทำให้มันทำงานได้โดยอัตโนมัติ อย่าลืมพิจารณาการเข้าถึงพร้อมกันและในทำนองเดียวกันหากคุณไปเส้นทางนั้น

แก้ไข: แน่นอนว่าคุณต้องตั้งค่าอินสแตนซ์ของการใช้งานแบบกำหนดเองของคุณเป็นตัวจัดการเริ่มต้นCookieHandler.setDefault()เพื่อรับการติดต่อกลับ ลืมบอกไปว่า.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.