How do I persist cookies when using HTTPUrlConnection?

后端 未结 4 873
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-01 03:33

I\'ve begun using the recommended HTTPUrlConnection and moved away from the DefaultHTTPClient. One of the things that I haven\'t been able to glue

相关标签:
4条回答
  • 2020-12-01 04:13

    Checkout the implementation in the link below. It saves the cookies by hostname like the original java.net.InMemoryCookieStore implementation does.

    Besides that it contains a SerializableHttpCookie to be able to serialize the complete HashMap into the SharedPreferences.

    https://gist.github.com/jacobtabak/78e226673d5a6a4c4367

    0 讨论(0)
  • 2020-12-01 04:31

    Its' taken me a few hours but I managed to build a custom cookie storage myself.

    You have to attach this by doing this:

    public class application extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
           CookieManager cmrCookieMan = new CookieManager(new MyCookieStore(this.objContext), CookiePolicy.ACCEPT_ALL);
           CookieHandler.setDefault(cmrCookieMan);
           }
        }
    

    Here's the actual storage:

    /*
     * This is a custom cookie storage for the application. This
     * will store all the cookies to the shared preferences so that it persists
     * across application restarts.
     */
    class MyCookieStore implements CookieStore {
    
        /*
         * The memory storage of the cookies
         */
        private Map<URI, List<HttpCookie>> mapCookies = new HashMap<URI, List<HttpCookie>>();
        /*
         * The instance of the shared preferences
         */
        private final SharedPreferences spePreferences;
    
        /*
         * @see java.net.CookieStore#add(java.net.URI, java.net.HttpCookie)
         */
        public void add(URI uri, HttpCookie cookie) {
    
            System.out.println("add");
            System.out.println(cookie.toString());
    
            List<HttpCookie> cookies = mapCookies.get(uri);
            if (cookies == null) {
                cookies = new ArrayList<HttpCookie>();
                mapCookies.put(uri, cookies);
            }
            cookies.add(cookie);
    
            Editor ediWriter = spePreferences.edit();
            HashSet<String> setCookies = new HashSet<String>();
            setCookies.add(cookie.toString());
            ediWriter.putStringSet(uri.toString(), spePreferences.getStringSet(uri.toString(), setCookies));
            ediWriter.commit();
    
        }
    
       /*
        * Constructor
        * 
        * @param  ctxContext the context of the Activity
        */
        @SuppressWarnings("unchecked")
        public MyCookieStore(Context ctxContext) {
    
            spePreferences = ctxContext.getSharedPreferences("CookiePrefsFile", 0);
            Map<String, ?> prefsMap = spePreferences.getAll();
    
            for(Map.Entry<String, ?> entry : prefsMap.entrySet()) {
    
                for (String strCookie : (HashSet<String>) entry.getValue()) {
    
                    if (!mapCookies.containsKey(entry.getKey())) {
    
                        List<HttpCookie> lstCookies = new ArrayList<HttpCookie>();
                        lstCookies.addAll(HttpCookie.parse(strCookie));
    
                        try {
    
                            mapCookies.put(new URI(entry.getKey()), lstCookies);
    
                        } catch (URISyntaxException e) {
    
                            e.printStackTrace();
    
                        }
    
                    } else {
    
                        List<HttpCookie> lstCookies = mapCookies.get(entry.getKey());
                        lstCookies.addAll(HttpCookie.parse(strCookie));
    
                        try {
    
                            mapCookies.put(new URI(entry.getKey()), lstCookies);
    
                        } catch (URISyntaxException e) {
    
                            e.printStackTrace();
    
                        }
    
                    }
    
                    System.out.println(entry.getKey() + ": " + strCookie);
    
                }
    
            }
    
        }
    
        /*
         * @see java.net.CookieStore#get(java.net.URI)
         */
        public List<HttpCookie> get(URI uri) {
    
            List<HttpCookie> lstCookies = mapCookies.get(uri);
    
            if (lstCookies == null)
                mapCookies.put(uri, new ArrayList<HttpCookie>());
    
            return mapCookies.get(uri);
    
        }
    
        /*
         * @see java.net.CookieStore#removeAll()
         */
        public boolean removeAll() {
    
            mapCookies.clear();
            return true;
    
        }        
    
        /*
         * @see java.net.CookieStore#getCookies()
         */
        public List<HttpCookie> getCookies() {
    
            Collection<List<HttpCookie>> values = mapCookies.values();
    
            List<HttpCookie> result = new ArrayList<HttpCookie>();
            for (List<HttpCookie> value : values) {                
                result.addAll(value);                
            }
    
            return result;
    
        }
    
        /*
         * @see java.net.CookieStore#getURIs()
         */
        public List<URI> getURIs() {
    
            Set<URI> keys = mapCookies.keySet();
            return new ArrayList<URI>(keys);
    
        }
    
        /*
         * @see java.net.CookieStore#remove(java.net.URI, java.net.HttpCookie)
         */
        public boolean remove(URI uri, HttpCookie cookie) {
    
            List<HttpCookie> lstCookies = mapCookies.get(uri);
    
            if (lstCookies == null)
                return false;
    
            return lstCookies.remove(cookie);
    
        }
    
    }
    
    0 讨论(0)
  • 2020-12-01 04:35

    I used the answer above but changed my add method to the following to handle more than one cookie from the same URI (this cookie store with GAE was treating the session token and the remember token as two separate cookies from the same URI for some reason):

    public void add(URI uri, HttpCookie cookie) {
    
    
        List<HttpCookie> cookies = mapCookies.get(uri);
        if (cookies == null) {
            cookies = new ArrayList<HttpCookie>();
            mapCookies.put(uri, cookies);
        }
        cookies.add(cookie);
    
        Editor ediWriter = spePreferences.edit();
        HashSet<String> setCookies = new HashSet<String>();
        setCookies.add(cookie.toString());
        HashSet<String> emptyCookieSet = new HashSet<String>();
        if(spePreferences.contains(uri.toString())){
            emptyCookieSet = (HashSet<String>) spePreferences.getStringSet(uri.toString(), emptyCookieSet);
            if(!emptyCookieSet.isEmpty()){
                if(!emptyCookieSet.contains(cookie.toString())){
                emptyCookieSet.add(cookie.toString());
                ediWriter.putStringSet(uri.toString(), emptyCookieSet);
                }
            }
        }
        else{
            ediWriter.putStringSet(uri.toString(), setCookies);
        }
        ediWriter.commit();
    } 
    

    And to access and create a combined cookie:

    MyCookieStore store = new MyCookieStore(this.context, false);
    String cookie = TextUtils.join(",", store.get(new URI(URLString)));
    

    Attach to connection:

    URL urlToRequest = new URL(stringPath);
    HttpURLConnection urlConnection = (HttpURLConnection) urlToRequest.openConnection();
    urlConnection.setRequestProperty("Cookie", cookie); 
    
    0 讨论(0)
  • 2020-12-01 04:36

    There are some basic problems in many custom CookieStore implementation.

    The first problem is HttpCookie serialization into string - the HttpCookie.toString() method is not acceptable for this because its result is not suitable for the HttpCookie.parse(String header) method.

    The second problem: most of CookieStore implementation (for example, here) does not takes into account the format of HttpCookie.maxAge field. This is a number of seconds to cookie live. But if you simply persist its value and after some time unpersist it, it will be wrong. You must convert maxAge field into something like "expire_at" and persist it instead of maxAge.

    0 讨论(0)
提交回复
热议问题