2009-03-24 46 views
110

Tôi muốn thực hiện yêu cầu http đến máy chủ từ xa trong khi xử lý đúng cookie (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). Nó sẽ được tốt đẹp để bảo tồn bất kỳ và tất cả các cookie, nhưng thực sự là người duy nhất tôi quan tâm là cookie phiên.Tôi làm cách nào để thực hiện yêu cầu http bằng cookie trên Android?

Với java.net, có vẻ như cách ưu tiên để 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 nó dường như không có java.net.CookieManager.

Tôi có thể mã hóa tất cả bằng tay bằng cách kiểm tra tiêu đề http, nhưng có vẻ như phải có 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ì?

+3

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

+0

Bạn đã thử [ org.apache.http.cookie] (http://developer.android.com/reference/org/apache/http/cookie/package-summary.html)? –

Trả lời

89

Nó chỉ ra rằng tàu với Apache HttpClient 4.0, và tôi Google Android đã có thể tìm ra cách để làm điều đó bằng cách sử dụng "Mẫu dựa đăng nhập" ví dụ trong HttpClient docs:

http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/httpclient/src/examples/org/apache/http/examples/client/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 có hợp lệ hay không? – Praveen

+0

THANK YOU để giới thiệu tôi với BasicNameValuePairs. Họ đã giúp tôi. – bhekman

+2

Tôi nhận 'Phương thức getCookieStore() là không xác định cho kiểu HttpClient', tôi có phải thay đổi thành' List cookies = ((AbstractHttpClient) httpclient) .getCookieStore(). GetCookies(); '? Vì nếu tôi làm, nó hoạt động. –

0

Tôi không làm việc với google android nhưng tôi nghĩ rằng bạn sẽ tìm thấy nó không phải là khó để có được điều này làm việc. Nếu bạn đọc the relevant bit of the java tutorial, bạn sẽ thấy rằng trình đăng ký cookie được đăng ký nhận được cuộc gọi lại từ mã HTTP. Vì vậy, nếu không có mặc định (bạn đã kiểm tra nếu CookieHandler.getDefault() thực sự là null?) Sau đó bạn chỉ có thể mở rộng CookieHandler, thực hiện put/get và làm cho nó hoạt động khá nhiều 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 tuyến đường đó.

chỉnh sửa: Rõ ràng 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 cuộc gọi lại. Quên đề cập đến điều đó.

8

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 bạn cũng có thể đọc và đặt cookie HTTP theo cách này.

Bạn có thể đọc this article để biết thêm thông tin.

Tôi có thể chia sẻ sự yên tĩnh về mã của mình để chứng minh bạn có thể làm được 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; 
    } 
+0

Đ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

+0

Nó hoạt động tốt !! –

+0

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

3

Kể từ thư viện Apache bị phản, đối với những người muốn sử dụng HttpURLConncetion, tôi đã viết lớp này để gửi Nhận và gửi yêu cầu với sự giúp đỡ của this answer:

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"); 
    /* 
    * https://stackoverflow.com/questions/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())); 
    } 

    /* 
    * https://stackoverflow.com/questions/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! 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 cookie cho nó để có sẵn nếu người dùng đã giết ứng dụng và khởi chạy lại nó, chính xác tôi nên lưu trữ và ở đâu (như thế nào) –

Các vấn đề liên quan