Using cookies with Android volley library

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.

Thanks.


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:

  • HurlStack: Uses HttpUrlConnection under the hood
  • HttpClientStack: uses Apache HttpClient under the hood
  • Cookie management is the responsibility of those HttpStacks. And they each handle Cookies differently.

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

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

    // 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.

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

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

    // 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.


    vmirinov is right!

    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:

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

    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:

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

    See also Should HttpURLConnection with CookieManager automatically handle session cookies?

    链接地址: http://www.djcxy.com/p/87916.html

    上一篇: 会话cookie应该保存在共享偏好中吗?

    下一篇: 在Android排球库中使用Cookie