【问题标题】:Cookie management with Java URLConnection使用 Java URLConnection 管理 Cookie
【发布时间】:2015-06-22 03:06:28
【问题描述】:

我对 android 编程还很陌生,最近成功实现了 HTTP Post 请求,只是得知我的 cookie 没有在后续的 Post/Get 请求之间存储。我环顾了整个互联网,找到了一些关于 Android 的 Apache 客户端和 Java 的 HttpURLConnection 的示例。我在当前的课程中实现这两种方法都没有成功,所以我想知道是否有更多经验的人可以审查我的代码并提供建议。

回顾:

  1. 我的初始 POST 请求成功并通过了身份验证。
  2. 我的第二个 POST 请求没有保留初始 POST 请求中的 cookie。
  3. 是否有任何特定的实例或原因可以说明某人可能会选择 Apache 方法或 Java 实现?两者本身是平等的,还是一个提供比另一个更多的功能和灵活性?

感谢您的帮助,谢谢。

webCreate.java

import android.util.Log;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.HttpCookie;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

public class webCreate {

    private final String USER_AGENT = "Mozilla/5.0";


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

        CookieManager cookieManager = new CookieManager();
        CookieHandler.setDefault(cookieManager);
        HttpCookie cookie = new HttpCookie("lang", "en");


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

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

        //add request header
        con.setRequestProperty("User-Agent", USER_AGENT);

        int responseCode = con.getResponseCode();
        Log.d("sendGet", "\nSending 'GET' request to URL : " + url);


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


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

        in.close();

        //print result
        System.out.println(response.toString());
        Log.d("Response Code", response.toString());
    }

    // HTTP POST request
    String  sendPost(String url, String urlParams) throws Exception {

        CookieManager cookieManager = new CookieManager();
        CookieHandler.setDefault(cookieManager);
        HttpCookie cookie = new HttpCookie("lang", "en");

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

        //add request header
        con.setRequestMethod("POST");
        con.setRequestProperty("User-Agent", USER_AGENT);
        con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");

        // Send post request
        con.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        wr.writeBytes(urlParams);
        wr.flush();
        wr.close();

        int responseCode = con.getResponseCode();
        System.out.println("\nSending 'POST' request to URL : " + url);
        System.out.println("Post parameters : " + urlParams);
        System.out.println("Response Code : " + responseCode);

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

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

        System.out.println("Response Code : " + response);
        return  response.toString();
    }

}

【问题讨论】:

    标签: java android cookies http-post httpurlconnection


    【解决方案1】:

    您需要在每次调用外部维护您的 cookie 上下文,并在后续的 GET 和 POST 中提供相同的 cookie 存储。这对于 Java 实现和 Apache 的实现都是一样的。

    根据我的经验,Apache's HTTP components 比内置的 Java 实现要好。我花了很多时间尝试使用 Java 的实现编写一个实用程序,我最大的问题是超时。糟糕的 Web 服务器会挂起,导致连接无限期挂起。切换到 Apache 后,超时是可调的,我们没有更多挂起的线程。


    我将举一个使用 Apache 的示例。

    在您的父方法中创建CookieStore 实例:

    CookieStore cookieStore = new BasicCookieStore();
    

    然后在您的 GET 或 POST 实现中传入 CookieStore 实例并在构建 HttpClient 时使用它:

    public void sendGet(String url, CookieStore cookieStore) throws Exception {
        ...
        HttpClient client = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build();
    
        HttpGet request = new HttpGet(uri);  // or HttpPost...
        request.addHeader("User-Agent", USER_AGENT);
        HttpResponse response = client.execute(request);
    
        BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        ...
    }
    

    Android 已经扩展了java.net.HttpURLConnection 并推荐使用它,所以我也会给出一个大纲。

    HttpURLConnectionHttpsURLConnection 自动且透明地使用 CookieHandler 中设置的 CookieManagerCookieHandler 是虚拟机范围的,所以必须只设置一次。如果您为每个请求创建一个新的CookieManager,就像您在代码中所做的那样,它将清除之前请求中设置的所有 cookie。

    您不需要自己创建HttpCookie 的实例。当HttpURLConnection 收到来自服务器的 cookie 时,CookieManager 将接收 cookie 并存储它。未来对同一服务器的请求将自动发送先前设置的 cookie。

    因此,将此代码移动到您的应用程序设置中,这样它只会发生一次:

    CookieManager cookieManager = new CookieManager();
    CookieHandler.setDefault(cookieManager);
    

    【讨论】:

    • 感谢您的回复,我没有机会测试代码。我确实查看了您的反馈,它提出了另一个您可能无法解决的问题。使用您的示例并假设 sendGet 也是您的类的名称: sendGet webReq = new sendGet(); webReq.sendGet("www.google.com", cookieStore);如果我要发送第二个 webReq.sendGet,如果只有一个 sendGet 类的新实例,为什么还要再次发送 cookie?我希望这个问题是有道理的。这个文本框的格式有点难。
    • sendGet 是方法的名称,而不是类的名称。如果您愿意,可以在您的班级中存储对CookieStore 的引用。但是,无论如何,每次您创建一个新的 HttpClient 实例时,您都必须提供您在之前对同一站点的请求中使用的相同 CookieStore 实例。
    • 哦,好吧。我希望您的示例能够奏效,但 Android Studio 拒绝识别“HttpClientBuilder”,它确实重构了 HttpClient。
    • HttpClientBuilder 是 Apache 的 HTTP 组件的一部分。您是否将其合并到您的项目中并将其导入您的课程中?这可能会造成混淆,因为 Java 的类名称相似。
    • 我找到了 Apache 库的移植版本,但经过进一步研究,似乎 android 实际上建议使用 HttpUrlConnection,而不是 HttpClient。 android-developers.blogspot.com/2011/09/… ---您能否提供一个使用 HttpUrlConnection 而不是 HttpClient 设置/获取带有 post/get 的 cookie 的示例?
    猜你喜欢
    • 2016-06-20
    • 2010-11-30
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    相关资源
    最近更新 更多