使用cookie与Android volley库

时间:2022-10-22 20:42:02

Does anybody know how to attach a session cookie to the request using com.android.volley library? When I log in to a web site it gives me a session cookie. Browser would send that cookie back with any subsequent request. Volley does not seem to do that, at least not automatically.

有人知道如何使用com.android将会话cookie附加到请求中吗?凌空图书馆吗?当我登录到一个网站时,它会给我一个会话cookie。浏览器会在随后的任何请求中发送该cookie。凌空抽射似乎并不能做到这一点,至少不是自动的。

Thanks.

谢谢。

10 个解决方案

#1


52  

Volley doesn't actually make HTTP requests itself, and thus doesn't manage Cookies directly. It instead uses an instance of HttpStack to do this. There are two main implementations:

Volley实际上并不自己发出HTTP请求,因此不能直接管理cookie。相反,它使用HttpStack实例来实现这一点。有两个主要的实现:

  • HurlStack: Uses HttpUrlConnection under the hood
  • HurlStack:在引擎盖下面使用HttpUrlConnection
  • HttpClientStack: uses Apache HttpClient under the hood
  • HttpClientStack:在hood下使用Apache HttpClient

Cookie management is the responsibility of those HttpStacks. And they each handle Cookies differently.

Cookie管理是这些httpstack的职责。他们处理饼干的方式不同。

If you need to support < 2.3, then you should use the HttpClientStack:

如果您需要支持< 2.3,那么您应该使用HttpClientStack:

Configure an HttpClient instance, and pass that to Volley for it to use under the hood:

配置一个HttpClient实例,并将其传递给Volley,以便它在引擎盖下使用:

// If you need to directly manipulate cookies later on, hold onto this client
// object as it gives you access to the Cookie Store
DefaultHttpClient httpclient = new DefaultHttpClient();

CookieStore cookieStore = new BasicCookieStore();
httpclient.setCookieStore( cookieStore );

HttpStack httpStack = new HttpClientStack( httpclient );
RequestQueue requestQueue = Volley.newRequestQueue( context, httpStack  );

The advantage with this vs manually inserting cookies into the headers is that you get actual cookie management. Cookies in your store will properly respond to HTTP controls that expire or update them.

与手动将cookie插入头部相比,这样做的好处是可以得到实际的cookie管理。您的存储中的cookie将正确地响应过期或更新的HTTP控件。

I've gone a step further and sub-classed BasicCookieStore so that I can automatically persist my cookies to disk.

我更进一步,对BasicCookieStore进行了子类化,以便能够自动将cookie持久化到磁盘。

HOWEVER! If you don't need to support older versions of Android. Just use this method:

然而!如果你不需要支持旧版本的Android。只有使用这种方法:

// CookieStore is just an interface, you can implement it and do things like
// save the cookies to disk or what ever.
CookieStore cookieStore = new MyCookieStore();
CookieManager manager = new CookieManager( cookieStore, CookiePolicy.ACCEPT_ALL );
CookieHandler.setDefault( manager  );

// Optionally, you can just use the default CookieManager
CookieManager manager = new CookieManager();
CookieHandler.setDefault( manager  );

HttpURLConnection will query the CookieManager from that implicitly. HttpUrlConnection is also more performant and a bit cleaner to implement and work with IMO.

HttpURLConnection将隐式地查询CookieManager。HttpUrlConnection也更具有性能和更简洁的功能,可以与IMO一起实现和工作。

#2


39  

vmirinov is right!

vmirinov是正确的!

Here is how I solved the problem:

我是这样解决这个问题的:

Request class:

请求类:

public class StringRequest extends com.android.volley.toolbox.StringRequest {

    private final Map<String, String> _params;

    /**
     * @param method
     * @param url
     * @param params
     *            A {@link HashMap} to post with the request. Null is allowed
     *            and indicates no parameters will be posted along with request.
     * @param listener
     * @param errorListener
     */
    public StringRequest(int method, String url, Map<String, String> params, Listener<String> listener,
            ErrorListener errorListener) {
        super(method, url, listener, errorListener);

        _params = params;
    }

    @Override
    protected Map<String, String> getParams() {
        return _params;
    }

    /* (non-Javadoc)
     * @see com.android.volley.toolbox.StringRequest#parseNetworkResponse(com.android.volley.NetworkResponse)
     */
    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        // since we don't know which of the two underlying network vehicles
        // will Volley use, we have to handle and store session cookies manually
        MyApp.get().checkSessionCookie(response.headers);

        return super.parseNetworkResponse(response);
    }

    /* (non-Javadoc)
     * @see com.android.volley.Request#getHeaders()
     */
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = super.getHeaders();

        if (headers == null
                || headers.equals(Collections.emptyMap())) {
            headers = new HashMap<String, String>();
        }

        MyApp.get().addSessionCookie(headers);

        return headers;
    }
}

and MyApp:

和MyApp:

public class MyApp extends Application {
    private static final String SET_COOKIE_KEY = "Set-Cookie";
    private static final String COOKIE_KEY = "Cookie";
    private static final String SESSION_COOKIE = "sessionid";

    private static MyApp _instance;
  private RequestQueue _requestQueue;
  private SharedPreferences _preferences;

    public static MyApp get() {
        return _instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        _instance = this;
            _preferences = PreferenceManager.getDefaultSharedPreferences(this);
        _requestQueue = Volley.newRequestQueue(this);
    }

    public RequestQueue getRequestQueue() {
        return _requestQueue;
    }


    /**
     * Checks the response headers for session cookie and saves it
     * if it finds it.
     * @param headers Response Headers.
     */
    public final void checkSessionCookie(Map<String, String> headers) {
        if (headers.containsKey(SET_COOKIE_KEY)
                && headers.get(SET_COOKIE_KEY).startsWith(SESSION_COOKIE)) {
                String cookie = headers.get(SET_COOKIE_KEY);
                if (cookie.length() > 0) {
                    String[] splitCookie = cookie.split(";");
                    String[] splitSessionId = splitCookie[0].split("=");
                    cookie = splitSessionId[1];
                    Editor prefEditor = _preferences.edit();
                    prefEditor.putString(SESSION_COOKIE, cookie);
                    prefEditor.commit();
                }
            }
    }

    /**
     * Adds session cookie to headers if exists.
     * @param headers
     */
    public final void addSessionCookie(Map<String, String> headers) {
        String sessionId = _preferences.getString(SESSION_COOKIE, "");
        if (sessionId.length() > 0) {
            StringBuilder builder = new StringBuilder();
            builder.append(SESSION_COOKIE);
            builder.append("=");
            builder.append(sessionId);
            if (headers.containsKey(COOKIE_KEY)) {
                builder.append("; ");
                builder.append(headers.get(COOKIE_KEY));
            }
            headers.put(COOKIE_KEY, builder.toString());
        }
    }

}

#3


18  

The default HTTP transport code for Volley is HttpUrlConnection. If I am reading the documentation correctly, you need to opt into automatic session cookie support:

Volley的默认HTTP传输代码是HttpUrlConnection。如果我正确地阅读了文档,您需要选择自动会话cookie支持:

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

See also Should HttpURLConnection with CookieManager automatically handle session cookies?

还应该看到与CookieManager的HttpURLConnection自动处理会话cookie吗?

#4


10  

Guys try this in onCreate method of your AppController.java

请在AppController.java的onCreate方法中尝试一下

  CookieHandler.setDefault(new CookieManager());

Hope it'll save time of developers. I have wasted four hours in debugging and searching appropriate solution.

希望它能节省开发人员的时间。我浪费了4个小时调试和寻找合适的解决方案。

#5


9  

@Rastio solution doesn't work if there are multiple 'Set-Cookie' headers. I wrapped the default CookieManager cookie store and before adding a cookie I saved it in SharedPreferences using Gson to serialize the cookie.

如果有多个“Set-Cookie”头,@Rastio解决方案就不能工作。我包装了默认的CookieManager cookie存储,在添加cookie之前,我使用Gson将它保存在SharedPreferences中以序列化cookie。

This is an example of the cookie store wrapper:

这是cookie store包装器的一个示例:

import android.content.Context;
import android.net.Uri;
import android.util.Log;

import com.google.gson.Gson;

import java.net.CookieManager;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.util.List;

/**
 * Class that implements CookieStore interface. This class saves to SharedPreferences the session
 * cookie.
 *
 * Created by lukas.
 */
public class PersistentCookieStore implements CookieStore {

    private CookieStore mStore;
    private Context mContext;
    private Gson mGson;

    public PersistentCookieStore(Context context) {
        // prevent context leaking by getting the application context
        mContext = context.getApplicationContext();
        mGson = new Gson();

        // get the default in memory store and if there is a cookie stored in shared preferences,
        // we added it to the cookie store
        mStore = new CookieManager().getCookieStore();
        String jsonSessionCookie = Prefs.getJsonSessionCookie(mContext);
        if (!jsonSessionCookie.equals(Prefs.DEFAULT_STRING)) {
            HttpCookie cookie = mGson.fromJson(jsonSessionCookie, HttpCookie.class);
            mStore.add(URI.create(cookie.getDomain()), cookie);
        }
    }

    @Override
    public void add(URI uri, HttpCookie cookie) {
        if (cookie.getName().equals("sessionid")) {
            // if the cookie that the cookie store attempt to add is a session cookie,
            // we remove the older cookie and save the new one in shared preferences
            remove(URI.create(cookie.getDomain()), cookie);
            Prefs.saveJsonSessionCookie(mContext, mGson.toJson(cookie));
        }

        mStore.add(URI.create(cookie.getDomain()), cookie);
    }

    @Override
    public List<HttpCookie> get(URI uri) {
        return mStore.get(uri);
    }

    @Override
    public List<HttpCookie> getCookies() {
        return mStore.getCookies();
    }

    @Override
    public List<URI> getURIs() {
        return mStore.getURIs();
    }

    @Override
    public boolean remove(URI uri, HttpCookie cookie) {
        return mStore.remove(uri, cookie);
    }

    @Override
    public boolean removeAll() {
        return mStore.removeAll();
    }
}

Then, to use the cookie store just set in the CookieManager and that's it!

然后,要使用cookie存储,只需设置CookieManager就行了!

CookieManager cookieManager = new CookieManager(new PersistentCookieStore(mContext),
    CookiePolicy.ACCEPT_ORIGINAL_SERVER);
CookieHandler.setDefault(cookieManager);

#6


4  

I know the post and a little old, but we went through this recent problem, we need to share the session of a logged User between servers, and server side solution began to require a value to be provided by the client side, through cookie. One solution we found was to add a parameter to RequestQueue object, the code snippet in the method getRequestQueue before instantiating the RequestQueue found on the link below, and solve the problem, not sure how, but it started to work.

我知道这篇文章有点老,但是我们最近遇到了这个问题,我们需要在服务器之间共享日志用户的会话,服务器端解决方案开始要求客户端通过cookie提供一个值。我们发现的一种解决方案是向RequestQueue对象添加一个参数,即getRequestQueue方法中的代码片段,然后实例化下面链接中找到的RequestQueue,然后解决这个问题(不知道是如何解决的),但是它开始工作了。

Visit http://woxiangbo.iteye.com/blog/1769122

访问http://woxiangbo.iteye.com/blog/1769122

public class App extends Application {

    public static final String TAG = App.class.getSimpleName();

    private static App         mInstance;

    public static synchronized App getInstance() {
        return App.mInstance;
    }

    private RequestQueue mRequestQueue;

    public <T> void addToRequestQueue( final Request<T> req ) {
        req.setTag( App.TAG );
        this.getRequestQueue().add( req );
    }

    public <T> void addToRequestQueue( final Request<T> req, final String tag ) {
        req.setTag( TextUtils.isEmpty( tag ) ? App.TAG : tag );
        this.getRequestQueue().add( req );
    }

    public void cancelPendingRequests( final Object tag ) {
        if ( this.mRequestQueue != null ) {
            this.mRequestQueue.cancelAll( tag );
        }
    }

    public RequestQueue getRequestQueue() {

        if ( this.mRequestQueue == null ) {


            DefaultHttpClient mDefaultHttpClient = new DefaultHttpClient();

            final ClientConnectionManager mClientConnectionManager = mDefaultHttpClient.getConnectionManager();
            final HttpParams mHttpParams = mDefaultHttpClient.getParams();
            final ThreadSafeClientConnManager mThreadSafeClientConnManager = new ThreadSafeClientConnManager( mHttpParams, mClientConnectionManager.getSchemeRegistry() );

            mDefaultHttpClient = new DefaultHttpClient( mThreadSafeClientConnManager, mHttpParams );

            final HttpStack httpStack = new HttpClientStack( mDefaultHttpClient );

            this.mRequestQueue = Volley.newRequestQueue( this.getApplicationContext(), httpStack );
        }

        return this.mRequestQueue;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        App.mInstance = this;
    }
}

//set token value

/ /设置令牌的值

ObjectRequest.setHeader( "Cookie", "JSESSIONID=" + tokenValueHere );

#7


2  

Use this method to use Volley with cookies to:

使用此方法与cookies进行截击:

  1. Use only very well tested code licenced under Apache 2 license
  2. 只使用经过良好测试的Apache 2许可的代码
  3. Make as many requests as you'd like at the same time
  4. 同时提出尽可能多的要求
  5. Make sure cookies persist on the device
  6. 确保cookie保存在设备上
  7. Not having to reinvent the wheel
  8. 不需要重新发明*

My server uses cookies to authenticate and obviously I wanted to ensure that cookies persist on the device. So my solution was to use PersistentCookieStore and SerializableCookie classes from Asynchronous Http Client for Android.

我的服务器使用cookie进行身份验证,显然我希望确保cookie在设备上持久存在。我的解决方案是使用来自Android的异步Http客户机的PersistentCookieStore和serizabalilecookie类。

First, in order to enable concurrent requests, an Apache HttpClient v4.3 port for Android is needed - one that comes with the system is outdated. More info here. I use Gradle, so this is how I imported it:

首先,为了启用并发请求,需要为Android提供一个Apache HttpClient v4.3端口——系统附带的端口已经过时了。更多的信息在这里。我使用的是等级,所以我是这样导入的:

dependencies {
    compile group: 'org.apache.httpcomponents' , name: 'httpclient-android' , version: '4.3.3'
}

Function to get RequestQueue (in my class that extends Application):

函数获取RequestQueue(在扩展应用程序的类中):

private RequestQueue mRequestQueue;
private CloseableHttpClient httpClient;

...

public RequestQueue getRequestQueue() {
    if (mRequestQueue == null) {
        httpClient = HttpClients.custom()
            .setConnectionManager(new PoolingHttpClientConnectionManager())
            .setDefaultCookieStore(new PersistentCookieStore(getApplicationContext()))
            .build();
        mRequestQueue = Volley.newRequestQueue(getApplicationContext(), new HttpClientStack(httpClient));
    }
    return mRequestQueue;
}

This is how I queue up a Request

这就是我排队请求的方式

public <T> void addToRequestQueue(Request<T> req, String tag) {
    req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
    getRequestQueue().add(req);
}

That's it!

就是这样!

#8


1  

If you have already started implementing your application by using the Loopj library, you will notice that you can't use new HttpClient instance in Volley.newRequestQUeue() because you will get various errors about not closing your previous connection etc.

如果您已经开始使用Loopj库实现您的应用程序,您将注意到不能在Volley.newRequestQUeue()中使用新的HttpClient实例,因为您将会在没有关闭之前的连接等方面收到各种错误。

Errors like:

错误:

java.lang.IllegalStateException: No wrapped connection

Invalid use of SingleClientConnManager: connection still allocated.

Now sometimes it takes time to refactor all your old API calls and rewrite them using volley, but you can use volley and loopj at the same time and share a cookiestore between those two until you write everything in volley (use volley instead of loopj, it is much better :) ).

有时需要时间重构你的旧API调用重写他们使用凌空抽射,但您可以使用截击和loopj同时共享一个cookiestore这两个之间,直到你写的一切凌空(使用凌空而不是loopj要好得多:))。

This is how you can share HttpClient and CookieStore from loopj with volley.

这是您如何与loopj共享HttpClient和CookieStore与volley的方式。

// For example you initialize loopj first
private static AsyncHttpClient client = new AsyncHttpClient();
sCookieStore = new PersistentCookieStore(getSomeContextHere());
client.setTimeout(DEFAULT_TIMEOUT);
client.setMaxConnections(12);
client.setCookieStore(sCookieStore);
client.setThreadPool(((ThreadPoolExecutor) Executors.newCachedThreadPool()));

public static RequestQueue getRequestQueue(){
    if(mRequestQueue == null){

    HttpClient httpclient = KkstrRestClient.getClient().getHttpClient();

    ((AbstractHttpClient) httpclient).setCookieStore( ApplicationController.getCookieStore() );

    HttpStack httpStack = new HttpClientStack(httpclient);

    mRequestQueue = Volley.newRequestQueue(getContext(), httpStack);
    }

    return mRequestQueue;
}

This happened to me, we started using loopj. After 50 000 lines of code and discovery that loopj doesn't always work like expected we decided to switch to Volley.

这发生在我身上,我们开始用loopj。在5万行代码和发现loopj并不总是像预期的那样工作之后,我们决定切换到截击。

#9


0  

The answer of @CommonsWare is the one I'd use. However, it looks like KitKat is having some bugs when that's done (When you create a CookieManager with custom CookieStore which you need if you want persistent Cookies). Given the fact that regardless of the implementation of the CookieStore that is used, Volley would throw a NullpointerException, I had to create my own CookieHandler... use it if you find it helpful.

@CommonsWare的答案是我要用的。但是,看起来KitKat在这个过程中出现了一些bug(当您创建一个带有定制CookieManager的CookieManager时,如果您想要持久的cookie,则需要它)。考虑到不管使用的是CookieStore的实现,Volley都会抛出NullpointerException,我必须创建自己的CookieHandler…如果你觉得有用就用它。

public class MyCookieHandler extends CookieHandler {

private static final String VERSION_ZERO_HEADER = "Set-cookie";

private static final String VERSION_ONE_HEADER = "Set-cookie2";
private static final String COOKIE_HEADER = "Cookie";

private static final String COOKIE_FILE = "Cookies";
private Map<String, Map<String, HttpCookie>> urisMap;

private Context context;

public MyCookieHandler(Context context) {

    this.context = context;
    loadCookies();

}

@SuppressWarnings("unchecked")
private void loadCookies() {
    File file = context.getFileStreamPath(COOKIE_FILE);
    if (file.exists())
        try {

            FileInputStream fis = context.openFileInput(COOKIE_FILE);
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    fis));
            String line = br.readLine();
            StringBuilder sb = new StringBuilder();
            while (line != null) {
                sb.append(line);
                line = br.readLine();
            }
            Log.d("MyCookieHandler.loadCookies", sb.toString());
            JSONObject jsonuris = new JSONObject(sb.toString());
            urisMap = new HashMap<String, Map<String, HttpCookie>>();
            Iterator<String> jsonurisiter = jsonuris.keys();

            while (jsonurisiter.hasNext()) {
                String prop = jsonurisiter.next();
                HashMap<String, HttpCookie> cookiesMap = new HashMap<String, HttpCookie>();
                JSONObject jsoncookies = jsonuris.getJSONObject(prop);
                Iterator<String> jsoncookiesiter = jsoncookies.keys();
                while (jsoncookiesiter.hasNext()) {
                    String pprop = jsoncookiesiter.next();
                    cookiesMap.put(pprop,
                            jsonToCookie(jsoncookies.getJSONObject(pprop)));
                }
                urisMap.put(prop, cookiesMap);

            }

        } catch (Exception e) {

            e.printStackTrace();
        }
    else {
        urisMap = new HashMap<String, Map<String, HttpCookie>>();
    }
}

@Override
public Map<String, List<String>> get(URI arg0,
        Map<String, List<String>> arg1) throws IOException {
    Log.d("MyCookieHandler.get",
            "getting Cookies for domain: " + arg0.getHost());
    Map<String, HttpCookie> cookies = urisMap.get(arg0.getHost());
    if (cookies != null)
        for (Entry<String, HttpCookie> cookie : cookies.entrySet()) {
            if (cookie.getValue().hasExpired()) {
                cookies.remove(cookie.getKey());
            }
        }

    if (cookies == null || cookies.isEmpty()) {
        Log.d("MyCookieHandler.get", "======");
        return Collections.emptyMap();
    }
    Log.d("MyCookieHandler.get",
            "Cookie : " + TextUtils.join("; ", cookies.values()));
    Log.d("MyCookieHandler.get", "======");
    return Collections.singletonMap(COOKIE_HEADER, Collections
            .singletonList(TextUtils.join("; ", cookies.values())));
}

@Override
public void put(URI uri, Map<String, List<String>> arg1) throws IOException {
    Map<String, HttpCookie> cookies = parseCookies(arg1);
    Log.d("MyCookieHandler.put",
            "saving Cookies for domain: " + uri.getHost());

    addCookies(uri, cookies);
    Log.d("MyCookieHandler.put",
            "Cookie : " + TextUtils.join("; ", cookies.values()));
    Log.d("MyCookieHandler.put", "======");

}

private void addCookies(URI uri, Map<String, HttpCookie> cookies) {
    if (!cookies.isEmpty()) {
        if (urisMap.get(uri.getHost()) == null) {
            urisMap.put(uri.getHost(), cookies);
        } else {
            urisMap.get(uri.getHost()).putAll(cookies);
        }
        saveCookies();
    }
}

private void saveCookies() {
    try {
        FileOutputStream fos = context.openFileOutput(COOKIE_FILE,
                Context.MODE_PRIVATE);

        JSONObject jsonuris = new JSONObject();
        for (Entry<String, Map<String, HttpCookie>> uris : urisMap
                .entrySet()) {
            JSONObject jsoncookies = new JSONObject();
            for (Entry<String, HttpCookie> savedCookies : uris.getValue()
                    .entrySet()) {
                jsoncookies.put(savedCookies.getKey(),
                        cookieToJson(savedCookies.getValue()));
            }
            jsonuris.put(uris.getKey(), jsoncookies);
        }
        fos.write(jsonuris.toString().getBytes());
        fos.close();
        Log.d("MyCookieHandler.addCookies", jsonuris.toString());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static JSONObject cookieToJson(HttpCookie cookie) {
    JSONObject jsoncookie = new JSONObject();
    try {
        jsoncookie.put("discard", cookie.getDiscard());
        jsoncookie.put("maxAge", cookie.getMaxAge());
        jsoncookie.put("secure", cookie.getSecure());
        jsoncookie.put("version", cookie.getVersion());
        jsoncookie.put("comment", cookie.getComment());
        jsoncookie.put("commentURL", cookie.getCommentURL());
        jsoncookie.put("domain", cookie.getDomain());
        jsoncookie.put("name", cookie.getName());
        jsoncookie.put("path", cookie.getPath());
        jsoncookie.put("portlist", cookie.getPortlist());
        jsoncookie.put("value", cookie.getValue());

    } catch (JSONException e) {

        e.printStackTrace();
    }

    return jsoncookie;
}

private static HttpCookie jsonToCookie(JSONObject jsonObject) {
    HttpCookie httpCookie;
    try {
        httpCookie = new HttpCookie(jsonObject.getString("name"),
                jsonObject.getString("value"));
        if (jsonObject.has("comment"))
            httpCookie.setComment(jsonObject.getString("comment"));
        if (jsonObject.has("commentURL"))
            httpCookie.setCommentURL(jsonObject.getString("commentURL"));
        if (jsonObject.has("discard"))
            httpCookie.setDiscard(jsonObject.getBoolean("discard"));
        if (jsonObject.has("domain"))
            httpCookie.setDomain(jsonObject.getString("domain"));
        if (jsonObject.has("maxAge"))
            httpCookie.setMaxAge(jsonObject.getLong("maxAge"));
        if (jsonObject.has("path"))
            httpCookie.setPath(jsonObject.getString("path"));
        if (jsonObject.has("portlist"))
            httpCookie.setPortlist(jsonObject.getString("portlist"));
        if (jsonObject.has("secure"))
            httpCookie.setSecure(jsonObject.getBoolean("secure"));
        if (jsonObject.has("version"))
            httpCookie.setVersion(jsonObject.getInt("version"));
        return httpCookie;
    } catch (JSONException e) {

        e.printStackTrace();
    }
    return null;

}

private Map<String, HttpCookie> parseCookies(Map<String, List<String>> map) {
    Map<String, HttpCookie> response = new HashMap<String, HttpCookie>();

    for (Entry<String, List<String>> e : map.entrySet()) {
        String key = e.getKey();
        if (key != null
                && (key.equalsIgnoreCase(VERSION_ONE_HEADER) || key
                        .equalsIgnoreCase(VERSION_ZERO_HEADER))) {
            for (String cookie : e.getValue()) {
                try {
                    for (HttpCookie htpc : HttpCookie.parse(cookie)) {
                        response.put(htpc.getName(), htpc);
                    }
                } catch (Exception e1) {

                    Log.e("MyCookieHandler.parseCookies",
                            "Error parsing cookies", e1);
                }
            }

        }
    }
    return response;

}
}

This answer hasn't been thoroughly tested. I used JSON to serialize Cookies, because well, that class don't implement Serializable and it's final.

这个答案还没有经过彻底的测试。我使用JSON来序列化cookie,因为这个类没有实现Serializable,它是最终的。

#10


-2  

Here is one of the simplest working examples. I do not like REST that is not restfull. But I guess everything goes as a learning experience. Most important thing to notice in the following example is that curlget.php does not have session_start. What language you use to write that part is up to you. In the following example it could be anything from java to rust. It could also locate anywhere.

下面是一个最简单的工作示例。我不喜欢不休息的休息。但我想一切都是学习的过程。在下面的示例中要注意的最重要的事情是curlget。php没有session_start。你用什么语言写那部分取决于你。在下面的例子中,它可以是任何东西,从java到rust。它也可以定位在任何地方。

login.php

login。

PHP Code:

PHP代码:

<?php
session_start();
//we store any POST/GET request to session
$_SESSION['un'] = $_REQUEST['username'];
userinfo.php
PHP Code:
<?php
session_start();
echo json_encode($_SESSION['un']);

curlget.php PHP Code:

curlget。php的php代码:

<?php
$ch = curl_init();
//we do login and get the session_id in from it's responce headers
curl_setopt($ch, CURLOPT_URL,"http://localhost/login.php");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,"username=test");
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec ($ch);
//we get the cookie from response header with the hardest possible way
//most platforms have tools for these
preg_match_all('/^Set-Cookie:\s*([^\r\n]*)/mi', $result, $ms);
$cookies = array();
foreach ($ms[1] as $m) {
    list($name, $value) = explode('=', $m, 2);
    $cookies[$name] = $value;
}
$parts = explode(";",$cookies['PHPSESSID']);
//The SessionId finally 
$SID = $parts[0];
curl_close ($ch);

//GET request using the SID from previous call

//从先前的调用中使用SID获得请求

#1


52  

Volley doesn't actually make HTTP requests itself, and thus doesn't manage Cookies directly. It instead uses an instance of HttpStack to do this. There are two main implementations:

Volley实际上并不自己发出HTTP请求,因此不能直接管理cookie。相反,它使用HttpStack实例来实现这一点。有两个主要的实现:

  • HurlStack: Uses HttpUrlConnection under the hood
  • HurlStack:在引擎盖下面使用HttpUrlConnection
  • HttpClientStack: uses Apache HttpClient under the hood
  • HttpClientStack:在hood下使用Apache HttpClient

Cookie management is the responsibility of those HttpStacks. And they each handle Cookies differently.

Cookie管理是这些httpstack的职责。他们处理饼干的方式不同。

If you need to support < 2.3, then you should use the HttpClientStack:

如果您需要支持< 2.3,那么您应该使用HttpClientStack:

Configure an HttpClient instance, and pass that to Volley for it to use under the hood:

配置一个HttpClient实例,并将其传递给Volley,以便它在引擎盖下使用:

// If you need to directly manipulate cookies later on, hold onto this client
// object as it gives you access to the Cookie Store
DefaultHttpClient httpclient = new DefaultHttpClient();

CookieStore cookieStore = new BasicCookieStore();
httpclient.setCookieStore( cookieStore );

HttpStack httpStack = new HttpClientStack( httpclient );
RequestQueue requestQueue = Volley.newRequestQueue( context, httpStack  );

The advantage with this vs manually inserting cookies into the headers is that you get actual cookie management. Cookies in your store will properly respond to HTTP controls that expire or update them.

与手动将cookie插入头部相比,这样做的好处是可以得到实际的cookie管理。您的存储中的cookie将正确地响应过期或更新的HTTP控件。

I've gone a step further and sub-classed BasicCookieStore so that I can automatically persist my cookies to disk.

我更进一步,对BasicCookieStore进行了子类化,以便能够自动将cookie持久化到磁盘。

HOWEVER! If you don't need to support older versions of Android. Just use this method:

然而!如果你不需要支持旧版本的Android。只有使用这种方法:

// CookieStore is just an interface, you can implement it and do things like
// save the cookies to disk or what ever.
CookieStore cookieStore = new MyCookieStore();
CookieManager manager = new CookieManager( cookieStore, CookiePolicy.ACCEPT_ALL );
CookieHandler.setDefault( manager  );

// Optionally, you can just use the default CookieManager
CookieManager manager = new CookieManager();
CookieHandler.setDefault( manager  );

HttpURLConnection will query the CookieManager from that implicitly. HttpUrlConnection is also more performant and a bit cleaner to implement and work with IMO.

HttpURLConnection将隐式地查询CookieManager。HttpUrlConnection也更具有性能和更简洁的功能,可以与IMO一起实现和工作。

#2


39  

vmirinov is right!

vmirinov是正确的!

Here is how I solved the problem:

我是这样解决这个问题的:

Request class:

请求类:

public class StringRequest extends com.android.volley.toolbox.StringRequest {

    private final Map<String, String> _params;

    /**
     * @param method
     * @param url
     * @param params
     *            A {@link HashMap} to post with the request. Null is allowed
     *            and indicates no parameters will be posted along with request.
     * @param listener
     * @param errorListener
     */
    public StringRequest(int method, String url, Map<String, String> params, Listener<String> listener,
            ErrorListener errorListener) {
        super(method, url, listener, errorListener);

        _params = params;
    }

    @Override
    protected Map<String, String> getParams() {
        return _params;
    }

    /* (non-Javadoc)
     * @see com.android.volley.toolbox.StringRequest#parseNetworkResponse(com.android.volley.NetworkResponse)
     */
    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        // since we don't know which of the two underlying network vehicles
        // will Volley use, we have to handle and store session cookies manually
        MyApp.get().checkSessionCookie(response.headers);

        return super.parseNetworkResponse(response);
    }

    /* (non-Javadoc)
     * @see com.android.volley.Request#getHeaders()
     */
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = super.getHeaders();

        if (headers == null
                || headers.equals(Collections.emptyMap())) {
            headers = new HashMap<String, String>();
        }

        MyApp.get().addSessionCookie(headers);

        return headers;
    }
}

and MyApp:

和MyApp:

public class MyApp extends Application {
    private static final String SET_COOKIE_KEY = "Set-Cookie";
    private static final String COOKIE_KEY = "Cookie";
    private static final String SESSION_COOKIE = "sessionid";

    private static MyApp _instance;
  private RequestQueue _requestQueue;
  private SharedPreferences _preferences;

    public static MyApp get() {
        return _instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        _instance = this;
            _preferences = PreferenceManager.getDefaultSharedPreferences(this);
        _requestQueue = Volley.newRequestQueue(this);
    }

    public RequestQueue getRequestQueue() {
        return _requestQueue;
    }


    /**
     * Checks the response headers for session cookie and saves it
     * if it finds it.
     * @param headers Response Headers.
     */
    public final void checkSessionCookie(Map<String, String> headers) {
        if (headers.containsKey(SET_COOKIE_KEY)
                && headers.get(SET_COOKIE_KEY).startsWith(SESSION_COOKIE)) {
                String cookie = headers.get(SET_COOKIE_KEY);
                if (cookie.length() > 0) {
                    String[] splitCookie = cookie.split(";");
                    String[] splitSessionId = splitCookie[0].split("=");
                    cookie = splitSessionId[1];
                    Editor prefEditor = _preferences.edit();
                    prefEditor.putString(SESSION_COOKIE, cookie);
                    prefEditor.commit();
                }
            }
    }

    /**
     * Adds session cookie to headers if exists.
     * @param headers
     */
    public final void addSessionCookie(Map<String, String> headers) {
        String sessionId = _preferences.getString(SESSION_COOKIE, "");
        if (sessionId.length() > 0) {
            StringBuilder builder = new StringBuilder();
            builder.append(SESSION_COOKIE);
            builder.append("=");
            builder.append(sessionId);
            if (headers.containsKey(COOKIE_KEY)) {
                builder.append("; ");
                builder.append(headers.get(COOKIE_KEY));
            }
            headers.put(COOKIE_KEY, builder.toString());
        }
    }

}

#3


18  

The default HTTP transport code for Volley is HttpUrlConnection. If I am reading the documentation correctly, you need to opt into automatic session cookie support:

Volley的默认HTTP传输代码是HttpUrlConnection。如果我正确地阅读了文档,您需要选择自动会话cookie支持:

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

See also Should HttpURLConnection with CookieManager automatically handle session cookies?

还应该看到与CookieManager的HttpURLConnection自动处理会话cookie吗?

#4


10  

Guys try this in onCreate method of your AppController.java

请在AppController.java的onCreate方法中尝试一下

  CookieHandler.setDefault(new CookieManager());

Hope it'll save time of developers. I have wasted four hours in debugging and searching appropriate solution.

希望它能节省开发人员的时间。我浪费了4个小时调试和寻找合适的解决方案。

#5


9  

@Rastio solution doesn't work if there are multiple 'Set-Cookie' headers. I wrapped the default CookieManager cookie store and before adding a cookie I saved it in SharedPreferences using Gson to serialize the cookie.

如果有多个“Set-Cookie”头,@Rastio解决方案就不能工作。我包装了默认的CookieManager cookie存储,在添加cookie之前,我使用Gson将它保存在SharedPreferences中以序列化cookie。

This is an example of the cookie store wrapper:

这是cookie store包装器的一个示例:

import android.content.Context;
import android.net.Uri;
import android.util.Log;

import com.google.gson.Gson;

import java.net.CookieManager;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.util.List;

/**
 * Class that implements CookieStore interface. This class saves to SharedPreferences the session
 * cookie.
 *
 * Created by lukas.
 */
public class PersistentCookieStore implements CookieStore {

    private CookieStore mStore;
    private Context mContext;
    private Gson mGson;

    public PersistentCookieStore(Context context) {
        // prevent context leaking by getting the application context
        mContext = context.getApplicationContext();
        mGson = new Gson();

        // get the default in memory store and if there is a cookie stored in shared preferences,
        // we added it to the cookie store
        mStore = new CookieManager().getCookieStore();
        String jsonSessionCookie = Prefs.getJsonSessionCookie(mContext);
        if (!jsonSessionCookie.equals(Prefs.DEFAULT_STRING)) {
            HttpCookie cookie = mGson.fromJson(jsonSessionCookie, HttpCookie.class);
            mStore.add(URI.create(cookie.getDomain()), cookie);
        }
    }

    @Override
    public void add(URI uri, HttpCookie cookie) {
        if (cookie.getName().equals("sessionid")) {
            // if the cookie that the cookie store attempt to add is a session cookie,
            // we remove the older cookie and save the new one in shared preferences
            remove(URI.create(cookie.getDomain()), cookie);
            Prefs.saveJsonSessionCookie(mContext, mGson.toJson(cookie));
        }

        mStore.add(URI.create(cookie.getDomain()), cookie);
    }

    @Override
    public List<HttpCookie> get(URI uri) {
        return mStore.get(uri);
    }

    @Override
    public List<HttpCookie> getCookies() {
        return mStore.getCookies();
    }

    @Override
    public List<URI> getURIs() {
        return mStore.getURIs();
    }

    @Override
    public boolean remove(URI uri, HttpCookie cookie) {
        return mStore.remove(uri, cookie);
    }

    @Override
    public boolean removeAll() {
        return mStore.removeAll();
    }
}

Then, to use the cookie store just set in the CookieManager and that's it!

然后,要使用cookie存储,只需设置CookieManager就行了!

CookieManager cookieManager = new CookieManager(new PersistentCookieStore(mContext),
    CookiePolicy.ACCEPT_ORIGINAL_SERVER);
CookieHandler.setDefault(cookieManager);

#6


4  

I know the post and a little old, but we went through this recent problem, we need to share the session of a logged User between servers, and server side solution began to require a value to be provided by the client side, through cookie. One solution we found was to add a parameter to RequestQueue object, the code snippet in the method getRequestQueue before instantiating the RequestQueue found on the link below, and solve the problem, not sure how, but it started to work.

我知道这篇文章有点老,但是我们最近遇到了这个问题,我们需要在服务器之间共享日志用户的会话,服务器端解决方案开始要求客户端通过cookie提供一个值。我们发现的一种解决方案是向RequestQueue对象添加一个参数,即getRequestQueue方法中的代码片段,然后实例化下面链接中找到的RequestQueue,然后解决这个问题(不知道是如何解决的),但是它开始工作了。

Visit http://woxiangbo.iteye.com/blog/1769122

访问http://woxiangbo.iteye.com/blog/1769122

public class App extends Application {

    public static final String TAG = App.class.getSimpleName();

    private static App         mInstance;

    public static synchronized App getInstance() {
        return App.mInstance;
    }

    private RequestQueue mRequestQueue;

    public <T> void addToRequestQueue( final Request<T> req ) {
        req.setTag( App.TAG );
        this.getRequestQueue().add( req );
    }

    public <T> void addToRequestQueue( final Request<T> req, final String tag ) {
        req.setTag( TextUtils.isEmpty( tag ) ? App.TAG : tag );
        this.getRequestQueue().add( req );
    }

    public void cancelPendingRequests( final Object tag ) {
        if ( this.mRequestQueue != null ) {
            this.mRequestQueue.cancelAll( tag );
        }
    }

    public RequestQueue getRequestQueue() {

        if ( this.mRequestQueue == null ) {


            DefaultHttpClient mDefaultHttpClient = new DefaultHttpClient();

            final ClientConnectionManager mClientConnectionManager = mDefaultHttpClient.getConnectionManager();
            final HttpParams mHttpParams = mDefaultHttpClient.getParams();
            final ThreadSafeClientConnManager mThreadSafeClientConnManager = new ThreadSafeClientConnManager( mHttpParams, mClientConnectionManager.getSchemeRegistry() );

            mDefaultHttpClient = new DefaultHttpClient( mThreadSafeClientConnManager, mHttpParams );

            final HttpStack httpStack = new HttpClientStack( mDefaultHttpClient );

            this.mRequestQueue = Volley.newRequestQueue( this.getApplicationContext(), httpStack );
        }

        return this.mRequestQueue;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        App.mInstance = this;
    }
}

//set token value

/ /设置令牌的值

ObjectRequest.setHeader( "Cookie", "JSESSIONID=" + tokenValueHere );

#7


2  

Use this method to use Volley with cookies to:

使用此方法与cookies进行截击:

  1. Use only very well tested code licenced under Apache 2 license
  2. 只使用经过良好测试的Apache 2许可的代码
  3. Make as many requests as you'd like at the same time
  4. 同时提出尽可能多的要求
  5. Make sure cookies persist on the device
  6. 确保cookie保存在设备上
  7. Not having to reinvent the wheel
  8. 不需要重新发明*

My server uses cookies to authenticate and obviously I wanted to ensure that cookies persist on the device. So my solution was to use PersistentCookieStore and SerializableCookie classes from Asynchronous Http Client for Android.

我的服务器使用cookie进行身份验证,显然我希望确保cookie在设备上持久存在。我的解决方案是使用来自Android的异步Http客户机的PersistentCookieStore和serizabalilecookie类。

First, in order to enable concurrent requests, an Apache HttpClient v4.3 port for Android is needed - one that comes with the system is outdated. More info here. I use Gradle, so this is how I imported it:

首先,为了启用并发请求,需要为Android提供一个Apache HttpClient v4.3端口——系统附带的端口已经过时了。更多的信息在这里。我使用的是等级,所以我是这样导入的:

dependencies {
    compile group: 'org.apache.httpcomponents' , name: 'httpclient-android' , version: '4.3.3'
}

Function to get RequestQueue (in my class that extends Application):

函数获取RequestQueue(在扩展应用程序的类中):

private RequestQueue mRequestQueue;
private CloseableHttpClient httpClient;

...

public RequestQueue getRequestQueue() {
    if (mRequestQueue == null) {
        httpClient = HttpClients.custom()
            .setConnectionManager(new PoolingHttpClientConnectionManager())
            .setDefaultCookieStore(new PersistentCookieStore(getApplicationContext()))
            .build();
        mRequestQueue = Volley.newRequestQueue(getApplicationContext(), new HttpClientStack(httpClient));
    }
    return mRequestQueue;
}

This is how I queue up a Request

这就是我排队请求的方式

public <T> void addToRequestQueue(Request<T> req, String tag) {
    req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
    getRequestQueue().add(req);
}

That's it!

就是这样!

#8


1  

If you have already started implementing your application by using the Loopj library, you will notice that you can't use new HttpClient instance in Volley.newRequestQUeue() because you will get various errors about not closing your previous connection etc.

如果您已经开始使用Loopj库实现您的应用程序,您将注意到不能在Volley.newRequestQUeue()中使用新的HttpClient实例,因为您将会在没有关闭之前的连接等方面收到各种错误。

Errors like:

错误:

java.lang.IllegalStateException: No wrapped connection

Invalid use of SingleClientConnManager: connection still allocated.

Now sometimes it takes time to refactor all your old API calls and rewrite them using volley, but you can use volley and loopj at the same time and share a cookiestore between those two until you write everything in volley (use volley instead of loopj, it is much better :) ).

有时需要时间重构你的旧API调用重写他们使用凌空抽射,但您可以使用截击和loopj同时共享一个cookiestore这两个之间,直到你写的一切凌空(使用凌空而不是loopj要好得多:))。

This is how you can share HttpClient and CookieStore from loopj with volley.

这是您如何与loopj共享HttpClient和CookieStore与volley的方式。

// For example you initialize loopj first
private static AsyncHttpClient client = new AsyncHttpClient();
sCookieStore = new PersistentCookieStore(getSomeContextHere());
client.setTimeout(DEFAULT_TIMEOUT);
client.setMaxConnections(12);
client.setCookieStore(sCookieStore);
client.setThreadPool(((ThreadPoolExecutor) Executors.newCachedThreadPool()));

public static RequestQueue getRequestQueue(){
    if(mRequestQueue == null){

    HttpClient httpclient = KkstrRestClient.getClient().getHttpClient();

    ((AbstractHttpClient) httpclient).setCookieStore( ApplicationController.getCookieStore() );

    HttpStack httpStack = new HttpClientStack(httpclient);

    mRequestQueue = Volley.newRequestQueue(getContext(), httpStack);
    }

    return mRequestQueue;
}

This happened to me, we started using loopj. After 50 000 lines of code and discovery that loopj doesn't always work like expected we decided to switch to Volley.

这发生在我身上,我们开始用loopj。在5万行代码和发现loopj并不总是像预期的那样工作之后,我们决定切换到截击。

#9


0  

The answer of @CommonsWare is the one I'd use. However, it looks like KitKat is having some bugs when that's done (When you create a CookieManager with custom CookieStore which you need if you want persistent Cookies). Given the fact that regardless of the implementation of the CookieStore that is used, Volley would throw a NullpointerException, I had to create my own CookieHandler... use it if you find it helpful.

@CommonsWare的答案是我要用的。但是,看起来KitKat在这个过程中出现了一些bug(当您创建一个带有定制CookieManager的CookieManager时,如果您想要持久的cookie,则需要它)。考虑到不管使用的是CookieStore的实现,Volley都会抛出NullpointerException,我必须创建自己的CookieHandler…如果你觉得有用就用它。

public class MyCookieHandler extends CookieHandler {

private static final String VERSION_ZERO_HEADER = "Set-cookie";

private static final String VERSION_ONE_HEADER = "Set-cookie2";
private static final String COOKIE_HEADER = "Cookie";

private static final String COOKIE_FILE = "Cookies";
private Map<String, Map<String, HttpCookie>> urisMap;

private Context context;

public MyCookieHandler(Context context) {

    this.context = context;
    loadCookies();

}

@SuppressWarnings("unchecked")
private void loadCookies() {
    File file = context.getFileStreamPath(COOKIE_FILE);
    if (file.exists())
        try {

            FileInputStream fis = context.openFileInput(COOKIE_FILE);
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    fis));
            String line = br.readLine();
            StringBuilder sb = new StringBuilder();
            while (line != null) {
                sb.append(line);
                line = br.readLine();
            }
            Log.d("MyCookieHandler.loadCookies", sb.toString());
            JSONObject jsonuris = new JSONObject(sb.toString());
            urisMap = new HashMap<String, Map<String, HttpCookie>>();
            Iterator<String> jsonurisiter = jsonuris.keys();

            while (jsonurisiter.hasNext()) {
                String prop = jsonurisiter.next();
                HashMap<String, HttpCookie> cookiesMap = new HashMap<String, HttpCookie>();
                JSONObject jsoncookies = jsonuris.getJSONObject(prop);
                Iterator<String> jsoncookiesiter = jsoncookies.keys();
                while (jsoncookiesiter.hasNext()) {
                    String pprop = jsoncookiesiter.next();
                    cookiesMap.put(pprop,
                            jsonToCookie(jsoncookies.getJSONObject(pprop)));
                }
                urisMap.put(prop, cookiesMap);

            }

        } catch (Exception e) {

            e.printStackTrace();
        }
    else {
        urisMap = new HashMap<String, Map<String, HttpCookie>>();
    }
}

@Override
public Map<String, List<String>> get(URI arg0,
        Map<String, List<String>> arg1) throws IOException {
    Log.d("MyCookieHandler.get",
            "getting Cookies for domain: " + arg0.getHost());
    Map<String, HttpCookie> cookies = urisMap.get(arg0.getHost());
    if (cookies != null)
        for (Entry<String, HttpCookie> cookie : cookies.entrySet()) {
            if (cookie.getValue().hasExpired()) {
                cookies.remove(cookie.getKey());
            }
        }

    if (cookies == null || cookies.isEmpty()) {
        Log.d("MyCookieHandler.get", "======");
        return Collections.emptyMap();
    }
    Log.d("MyCookieHandler.get",
            "Cookie : " + TextUtils.join("; ", cookies.values()));
    Log.d("MyCookieHandler.get", "======");
    return Collections.singletonMap(COOKIE_HEADER, Collections
            .singletonList(TextUtils.join("; ", cookies.values())));
}

@Override
public void put(URI uri, Map<String, List<String>> arg1) throws IOException {
    Map<String, HttpCookie> cookies = parseCookies(arg1);
    Log.d("MyCookieHandler.put",
            "saving Cookies for domain: " + uri.getHost());

    addCookies(uri, cookies);
    Log.d("MyCookieHandler.put",
            "Cookie : " + TextUtils.join("; ", cookies.values()));
    Log.d("MyCookieHandler.put", "======");

}

private void addCookies(URI uri, Map<String, HttpCookie> cookies) {
    if (!cookies.isEmpty()) {
        if (urisMap.get(uri.getHost()) == null) {
            urisMap.put(uri.getHost(), cookies);
        } else {
            urisMap.get(uri.getHost()).putAll(cookies);
        }
        saveCookies();
    }
}

private void saveCookies() {
    try {
        FileOutputStream fos = context.openFileOutput(COOKIE_FILE,
                Context.MODE_PRIVATE);

        JSONObject jsonuris = new JSONObject();
        for (Entry<String, Map<String, HttpCookie>> uris : urisMap
                .entrySet()) {
            JSONObject jsoncookies = new JSONObject();
            for (Entry<String, HttpCookie> savedCookies : uris.getValue()
                    .entrySet()) {
                jsoncookies.put(savedCookies.getKey(),
                        cookieToJson(savedCookies.getValue()));
            }
            jsonuris.put(uris.getKey(), jsoncookies);
        }
        fos.write(jsonuris.toString().getBytes());
        fos.close();
        Log.d("MyCookieHandler.addCookies", jsonuris.toString());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static JSONObject cookieToJson(HttpCookie cookie) {
    JSONObject jsoncookie = new JSONObject();
    try {
        jsoncookie.put("discard", cookie.getDiscard());
        jsoncookie.put("maxAge", cookie.getMaxAge());
        jsoncookie.put("secure", cookie.getSecure());
        jsoncookie.put("version", cookie.getVersion());
        jsoncookie.put("comment", cookie.getComment());
        jsoncookie.put("commentURL", cookie.getCommentURL());
        jsoncookie.put("domain", cookie.getDomain());
        jsoncookie.put("name", cookie.getName());
        jsoncookie.put("path", cookie.getPath());
        jsoncookie.put("portlist", cookie.getPortlist());
        jsoncookie.put("value", cookie.getValue());

    } catch (JSONException e) {

        e.printStackTrace();
    }

    return jsoncookie;
}

private static HttpCookie jsonToCookie(JSONObject jsonObject) {
    HttpCookie httpCookie;
    try {
        httpCookie = new HttpCookie(jsonObject.getString("name"),
                jsonObject.getString("value"));
        if (jsonObject.has("comment"))
            httpCookie.setComment(jsonObject.getString("comment"));
        if (jsonObject.has("commentURL"))
            httpCookie.setCommentURL(jsonObject.getString("commentURL"));
        if (jsonObject.has("discard"))
            httpCookie.setDiscard(jsonObject.getBoolean("discard"));
        if (jsonObject.has("domain"))
            httpCookie.setDomain(jsonObject.getString("domain"));
        if (jsonObject.has("maxAge"))
            httpCookie.setMaxAge(jsonObject.getLong("maxAge"));
        if (jsonObject.has("path"))
            httpCookie.setPath(jsonObject.getString("path"));
        if (jsonObject.has("portlist"))
            httpCookie.setPortlist(jsonObject.getString("portlist"));
        if (jsonObject.has("secure"))
            httpCookie.setSecure(jsonObject.getBoolean("secure"));
        if (jsonObject.has("version"))
            httpCookie.setVersion(jsonObject.getInt("version"));
        return httpCookie;
    } catch (JSONException e) {

        e.printStackTrace();
    }
    return null;

}

private Map<String, HttpCookie> parseCookies(Map<String, List<String>> map) {
    Map<String, HttpCookie> response = new HashMap<String, HttpCookie>();

    for (Entry<String, List<String>> e : map.entrySet()) {
        String key = e.getKey();
        if (key != null
                && (key.equalsIgnoreCase(VERSION_ONE_HEADER) || key
                        .equalsIgnoreCase(VERSION_ZERO_HEADER))) {
            for (String cookie : e.getValue()) {
                try {
                    for (HttpCookie htpc : HttpCookie.parse(cookie)) {
                        response.put(htpc.getName(), htpc);
                    }
                } catch (Exception e1) {

                    Log.e("MyCookieHandler.parseCookies",
                            "Error parsing cookies", e1);
                }
            }

        }
    }
    return response;

}
}

This answer hasn't been thoroughly tested. I used JSON to serialize Cookies, because well, that class don't implement Serializable and it's final.

这个答案还没有经过彻底的测试。我使用JSON来序列化cookie,因为这个类没有实现Serializable,它是最终的。

#10


-2  

Here is one of the simplest working examples. I do not like REST that is not restfull. But I guess everything goes as a learning experience. Most important thing to notice in the following example is that curlget.php does not have session_start. What language you use to write that part is up to you. In the following example it could be anything from java to rust. It could also locate anywhere.

下面是一个最简单的工作示例。我不喜欢不休息的休息。但我想一切都是学习的过程。在下面的示例中要注意的最重要的事情是curlget。php没有session_start。你用什么语言写那部分取决于你。在下面的例子中,它可以是任何东西,从java到rust。它也可以定位在任何地方。

login.php

login。

PHP Code:

PHP代码:

<?php
session_start();
//we store any POST/GET request to session
$_SESSION['un'] = $_REQUEST['username'];
userinfo.php
PHP Code:
<?php
session_start();
echo json_encode($_SESSION['un']);

curlget.php PHP Code:

curlget。php的php代码:

<?php
$ch = curl_init();
//we do login and get the session_id in from it's responce headers
curl_setopt($ch, CURLOPT_URL,"http://localhost/login.php");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,"username=test");
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec ($ch);
//we get the cookie from response header with the hardest possible way
//most platforms have tools for these
preg_match_all('/^Set-Cookie:\s*([^\r\n]*)/mi', $result, $ms);
$cookies = array();
foreach ($ms[1] as $m) {
    list($name, $value) = explode('=', $m, 2);
    $cookies[$name] = $value;
}
$parts = explode(";",$cookies['PHPSESSID']);
//The SessionId finally 
$SID = $parts[0];
curl_close ($ch);

//GET request using the SID from previous call

//从先前的调用中使用SID获得请求