java 使用 HTTPUrlConnection 时如何保留 cookie?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12349266/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 08:31:30  来源:igfitidea点击:

How do I persist cookies when using HTTPUrlConnection?

javaandroidcookieshttpurlconnection

提问by Mridang Agarwalla

I've begun using the recommended HTTPUrlConnectionand moved away from the DefaultHTTPClient. One of the things that I haven't been able to glue back together is the use of a persistent cookie store. I'd like to simply attach a custom cookie handler/manager to my connection to store the cookies. The Android documentation hasn't been very helpful as it wraps up the subject about cookies in two lines.

我已经开始使用推荐的HTTPUrlConnection并远离DefaultHTTPClient. 我无法重新组合在一起的一件事是使用持久性 cookie 存储。我想简单地将自定义 cookie 处理程序/管理器附加到我的连接以存储 cookie。Android 文档并不是很有帮助,因为它将有关 cookie 的主题分为两行。

I've been using LoopJ's PersistentCookieStoreearlier and that worked beautifully.

我之前一直在使用 LoopJ PersistentCookieStore,效果很好。

Any idea on how I could set up a persistent cookie store in Android that I can attach to my HTTPUrlConnectionthat saves and retrieves cookies automatically?

关于如何在 Android 中设置持久性 cookie 存储区的任何想法,我可以将其附加到我的HTTPUrlConnection自动保存和检索 cookie 的位置?

Thanks

谢谢

采纳答案by Mridang Agarwalla

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

它花了我几个小时,但我设法自己建立了一个自定义的 cookie 存储。

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

    }

}

回答by StiggyBr0

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):

我使用了上面的答案,但将我的 add 方法更改为以下方法以处理来自同一 URI 的多个 cookie(出于某种原因,这个带有 GAE 的 cookie 存储将会话令牌和记忆令牌视为来自同一 URI 的两个单独的 cookie) :

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:

并访问和创建组合 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); 

回答by Ruslan Yanchyshyn

There are some basic problems in many custom CookieStoreimplementation.

许多自定义CookieStore实现存在一些基本问题。

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

第一个问题是HttpCookie序列化为字符串——该HttpCookie.toString()方法对此是不可接受的,因为其结果不适合该HttpCookie.parse(String header)方法。

The second problem: most of CookieStoreimplementation (for example, here) does not takes into account the format of HttpCookie.maxAgefield. 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 maxAgefield into something like "expire_at"and persist it instead of maxAge.

第二个问题:大部分CookieStore实现(例如这里)没有考虑HttpCookie.maxAge字段的格式。这是 cookie 存活的秒数。但如果你只是坚持它的价值,一段时间后又不坚持,那就错了。您必须将maxAgefield转换为类似的内容"expire_at"并将其持久化而不是maxAge.

回答by Ben Groot

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

在下面的链接中查看实现。它像原始 java.net.InMemoryCookieStore 实现一样按主机名保存 cookie。

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

除此之外,它还包含一个 SerializableHttpCookie 以便能够将完整的 HashMap 序列化到 SharedPreferences 中。

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

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