重用 HttpURLConnection 以保持会话活动

Posted

技术标签:

【中文标题】重用 HttpURLConnection 以保持会话活动【英文标题】:Reusing HttpURLConnection so as to keep session alive 【发布时间】:2012-05-29 16:56:57 【问题描述】:

我们有一个 android 应用程序,要求用户输入验证码的答案。 验证码是在我们的服务器上生成的。 当回复时,它被发送到服务器进行验证。

问题是,由于我必须在请求验证码后关闭 HttpURLConnection,然后我发现回复正在服务器上的不同会话上运行。 因此,验证码检查失败,因为它依赖于会话。

有没有办法让连接保持活跃,或者我应该走一条不同的路? 我知道在等效的 iPhone 应用程序中,它们保持“连接”状态,因此具有相同的 sessionid。

编辑:

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

    URL urlObj = new URL(urlPath);
    conn = (HttpURLConnection) urlObj.openConnection();

    if (urlPath.toLowerCase().startsWith("https:")) 
        initializeHttpsConnection((HttpsURLConnection) conn);
    
    conn.setRequestMethod("POST");
    conn.setRequestProperty("Content-Language", "en-US");
    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    conn.setRequestProperty("Content-Length", Integer.toString(bodyData.length));
    if (_sessionIdCookie != null) 
        conn.setRequestProperty("Cookie", _sessionIdCookie);
    
    // Connect
    conn.setDoInput(true);
    conn.setDoOutput(true);
    conn.connect();

【问题讨论】:

【参考方案1】:

通常,会话不会基于 http 连接本身而保留。那没有任何意义。会话通常通过客户端的 cookie 和服务器端的会话信息保持活动状态。 您需要做的是保存您收到的 cookie,然后在下次连接到服务器时设置该(那些)cookie。

要详细了解如何使用 HttpUrlConnection 类处理会话和 cookie,请阅读文档:http://developer.android.com/reference/java/net/HttpURLConnection.html

这里有一些摘录让你开始:

建立和维护一个潜在的长期会话 客户端和服务器,HttpURLConnection 包含一个可扩展的 cookie 经理。使用 CookieHandler 和 Cookie 管理器:

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

编辑:

对于那些使用 API 级别 8 或更低级别的用户,您需要使用 Apache 的库!

这里有一些参考代码:

 // Create a local instance of cookie store
    CookieStore cookieStore = new BasicCookieStore();

    // Create local HTTP context
    HttpContext localContext = new BasicHttpContext();
    // Bind custom cookie store to the local context
    localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

    HttpGet httpget = new HttpGet("http://www.google.com/"); 

    System.out.println("executing request " + httpget.getURI());

    // Pass local context as a parameter
    HttpResponse response = httpclient.execute(httpget, localContext);

上面的代码取自 Apache 的库示例。在这里能找到它: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/httpclient/src/examples/org/apache/http/examples/client/ClientCustomContext.java

编辑 2: 说清楚:

对于 Apache 库,您需要以某种方式将 cookie 管理对象与连接对象“连接”起来,并通过 HttpContext 对象来实现。

在 HttpUrlConnection 的情况下,这不是必需的。当您使用 CookieHandler 的静态方法 setDefault 时,您正在设置系统范围的 cookieHandler。以下是 CookieHandler.java 的摘录。注意变量名称(来自 Android 开源项目 (AOSP) 存储库):

 37 /**
 38      * Sets the system-wide cookie handler.
 39      */
 40     public static void setDefault(CookieHandler cHandler) 
 41         systemWideCookieHandler = cHandler;
 42     

【讨论】:

一旦我定义了“CookieManager”,我会添加一个保存 sessionid 的吗? 好的,我有一个重要的问题要问您:您使用的是 API 9+ (2.3+) 吗?如果是,您只需在连接之前添加它就可以了。如果您使用的是 2.2 或更低版本,您应该使用 org.apache 包中的 HttpClient。如果您正在使用 2.2,我将添加一些示例代码。 目前它设置为 2.3,但不确定我们是否会这样。可能会降到 2.2 之前,但不确定。似乎这里 99% 的设备都是 2.3+,所以应该没问题。 好的。所以你应该很好。试试看,让我知道它是否有效。我将添加与 Apache 库一起使用的代码,以方便下一个偶然发现此问题的人 仍然不确定它应该如何工作。我是否需要以某种方式连接到 cookie 管理器来连接?我已编辑以包含我的代码。【参考方案2】:

要使用HttpURLConnection 维护会话,您需要执行此部分

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

只有一次,而不是每次连接。好的候选人可以在Application.onCreate();内的应用程序启动

【讨论】:

以上是关于重用 HttpURLConnection 以保持会话活动的主要内容,如果未能解决你的问题,请参考以下文章

Java之HttpURLConnection的变态事: Keep-Alive

保持 HttpUrlConnection 调用之间的会话(本机/Webview)

JDBC 连接池:连接重用?

不断开连接HttpUrlConnection意味着资源缺乏或网络滞后

在页面之间重用websockets?

HttpURLConnection与HttpClient浅析AAAA