如何在 Android 上使用 cookies 发出 http 请求?

我希望在正确处理 Cookie 的同时向远程服务器发出 http 请求(例如,存储服务器发送的 Cookie,并在发出后续请求时发送这些 Cookie)。如果能保存所有的 cookie 就好了,但我真正关心的只有会话 cookie。

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

我可以通过检查 http 头来手工编写代码,但是看起来一定有更简单的方法。

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

126001 次浏览

我不与谷歌安卓工作,但我认为你会发现这不是很难得到这个工作。如果读取 Java 教程的相关部分,您将看到已注册的 cookie 处理程序从 HTTP 代码获得回调。

因此,如果没有默认值(是否检查了 CookieHandler.getDefault()是否真的为空?)然后,您可以简单地扩展 CookieHandler,实现 put/get,并使其非常自动地工作。如果采用这种方法,一定要考虑并发访问等问题。

edit: Obviously you'd have to set an instance of your custom implementation as the default handler through CookieHandler.setDefault() to receive the callbacks. Forgot to mention that.

It turns out that Google Android ships with Apache HttpClient 4.0, and I was able to figure out how to do it using the "Form based logon" example in the HttpClient 文档:

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

您可以阅读 这篇文章以获得更多信息。

I can share my peace of code to demonstrate how easy you can make it.

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

不推荐使用 Apache 库开始,对于那些想要使用 HttpURLConncetion的人,我编写了这个类来发送 Get 和 Post Request,并借助 这个答案:

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