2009-03-24 4 views
110

Я хотел бы сделать http-запрос на удаленный сервер при правильной обработке файлов cookie (например, сохранение файлов cookie, отправленных сервером, и отправка этих файлов cookie при выполнении последующих запросов). Было бы неплохо сохранить все и все файлы cookie, но на самом деле единственное, что мне волнует, - это cookie сеанса.Как сделать http-запрос с помощью файлов cookie на Android?

С помощью java.net, кажется, что предпочтительный способ сделать это - использовать java.net.CookieHandler (абстрактный базовый класс) и java.net.CookieManager (конкретная реализация). Android имеет java.net.CookieHandler, но у него, похоже, нет java.net.CookieManager.

Я могу закодировать все это вручную, проверив заголовки http, но похоже, что должен быть более простой способ.

Каков правильный способ сделать HTTP-запросы на Android при сохранении файлов cookie?

+3

Так же, как примечание более чем два года спустя: 'java.net.CookieManager' теперь поддерживается в Android с версии 2.3 (уровень API 9): http://developer.android.com/reference/java/net/CookieManager.html – Slauma

+0

Вы пытались [ org.apache.http.cookie] (http://developer.android.com/reference/org/apache/http/cookie/package-summary.html)? –

ответ

89

Оказывается, что Google Android поставляется с Apache HTTPClient 4.0, и я был в состоянии понять, как сделать это с помощью «входа формы на основе» пример в 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

Могу ли я узнать, как установить cookie-файлы в URL-адрес запроса, чтобы проверить сеанс, действительно ли он или нет? – Praveen

+0

СПАСИБО за то, что ознакомил меня с BasicNameValuePairs. Они мне помогли. – bhekman

+2

Я получаю 'Метод getCookieStore() не определен для типа HttpClient', мне нужно изменить на' List cookie = ((AbstractHttpClient) httpclient) .getCookieStore(). GetCookies(); '? Потому что, если я это сделаю, это сработает. –

0

Я не работаю с Google Android, но я думаю, вы обнаружите, что работать не так уж сложно. Если вы прочитали the relevant bit of the java tutorial, вы увидите, что зарегистрированный обработчик cookie получает обратные вызовы из кода HTTP.

Так что, если нет значения по умолчанию (вы проверили, действительно ли CookieHandler.getDefault() равно null?), То вы можете просто расширить CookieHandler, реализовать put/get и заставить его работать почти автоматически. Не забудьте рассмотреть параллельный доступ и тому подобное, если вы идете по этому маршруту.

Редактировать: Очевидно, вам нужно будет установить экземпляр вашей пользовательской реализации в качестве обработчика по умолчанию через CookieHandler.setDefault() для получения обратных вызовов. Забыл упомянуть об этом.

8

Cookie - это еще один HTTP-заголовок. Вы всегда можете установить его при вызове HTTP с помощью библиотеки apache или с помощью HTTPUrlConnection. В любом случае вы должны иметь возможность читать и устанавливать HTTP-файлы cookie таким образом.

Для получения дополнительной информации вы можете прочитать this article.

Я могу поделиться своим миром кода, чтобы продемонстрировать, насколько легко вы можете это сделать.

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

Это мне очень помогает, +1 get.setHeader («Cookie», «PHPSESSID =» + токен + «;»); сделайте работу – Oussaki

+0

Он отлично работает !! –

+0

@ Hesam: unfortunatley android устарел модуль apache. Поэтому сейчас его ответ не помогает. Есть ли другой способ сделать это с HttpURLConnection? –

3

С библиотеки Apache устарела, для тех, кто хочет использовать HttpURLConncetion, я написал этот класс, чтобы отправить Получить и сообщение запрос с помощью 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! Это мне очень помогло ! Теперь мне было интересно, хочу ли я сохранить файл cookie, чтобы он был доступен, если пользователь убил приложение и снова запустил его, что именно я должен хранить и где (как) –

Смежные вопросы