【问题标题】:How do I make an http request using cookies on Android?如何在 Android 上使用 cookie 发出 http 请求?
【发布时间】:2010-10-15 06:50:21
【问题描述】:

我想在正确处理 cookie 的同时向远程服务器发出 http 请求(例如,存储服务器发送的 cookie,并在我发出后续请求时发送这些 cookie)。保留所有 cookie 会很好,但实际上我唯一关心的是会话 cookie。

对于 java.net,似乎首选的方法是使用 java.net.CookieHandler(抽象基类)和 java.net.CookieManager(具体实现)。 Android有java.net.CookieHandler,但是好像没有java.net.CookieManager。

我可以通过检查 http 标头来手动编码,但似乎必须有更简单的方法。

在保留 cookie 的同时在 Android 上发出 http 请求的正确方法是什么?

【问题讨论】:

标签: java android http url cookies


【解决方案1】:

我不使用 google android,但我想你会发现让它工作并不难。如果您阅读the relevant bit of the java tutorial,您会看到已注册的cookiehandler 从HTTP 代码中获取回调。

因此,如果没有默认值(您是否检查过CookieHandler.getDefault() 是否真的为空?)那么您可以简单地扩展 CookieHandler,实现 put/get 并使其几乎自动工作。如果你走那条路,一定要考虑并发访问等。

编辑:显然,您必须通过CookieHandler.setDefault() 将自定义实现的实例设置为默认处理程序才能接收回调。忘记说了。

【讨论】:

    【解决方案2】:

    事实证明,Google Android 附带 Apache HttpClient 4.0,我能够使用HttpClient docs 中的“基于表单的登录”示例弄清楚如何做到这一点:

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

    【讨论】:

    • 请问如何设置 cookie 到 Request Url 以检查会话是否有效?
    • 感谢您向我介绍 BasicNameValuePairs。他们帮助了我。
    • 我得到The method getCookieStore() is undefined for the type HttpClient,我必须更改为List&lt;Cookie&gt; cookies = ((AbstractHttpClient) httpclient).getCookieStore().getCookies(); 吗?因为如果我这样做,它会起作用。
    • @Praveen 看看这里保存 Cookie:stackoverflow.com/a/5989115/2615737
    • @emmby:不幸的是 android 已弃用 apache 模块。所以现在他的回答没有帮助。还有其他方法可以用 HttpURLConnection 做到这一点吗?
    【解决方案3】:

    cookie 只是另一个 HTTP 标头。在使用 apache 库或 HTTPUrlConnection 进行 HTTP 调用时,您始终可以设置它。无论哪种方式,您都应该能够以这种方式读取和设置 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;
        }
    

    【讨论】:

    • 这对我很有帮助,+1 get.setHeader("Cookie", "PHPSESSID=" + token + ";");做这项工作
    • @Hesam :不幸的是 android 已弃用 apache 模块。所以现在他的回答没有帮助。有没有另一种方法可以用 HttpURLConnection 做到这一点?
    【解决方案4】:

    由于 Apache 库已弃用,对于那些想要使用 HttpURLConncetion 的人,我编写了这个类来发送 Get 和 Post Request 在 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;
    }
    }
    

    【讨论】:

    • 好班米拉德!这对我帮助很大 !现在,我想知道,如果我想保存 cookie 以便在用户杀死应用程序并再次启动它时可用,我应该存储什么以及在哪里(如何)
    猜你喜欢
    • 2019-02-15
    • 2019-02-13
    • 2020-09-13
    • 2011-03-31
    • 2023-02-06
    • 2013-02-03
    • 1970-01-01
    相关资源
    最近更新 更多