How to parse a cookie string

后端 未结 9 1852
眼角桃花
眼角桃花 2020-12-08 04:47

I would like to take a Cookie string (as it might be returned in a Set-Cookie header) and be able to easily modify parts of it, specifically the expiration date.

I s

相关标签:
9条回答
  • 2020-12-08 04:52

    If you happen to have Netty HTTP codec installed, you can also use io.netty.handler.codec.http.cookie.ServerCookieDecoder.LAX|STRICT. Very convenient.

    0 讨论(0)
  • 2020-12-08 04:54
    CookieManager cookieManager = new CookieManager();
            CookieHandler.setDefault(cookieManager);
            HttpCookie cookie = new HttpCookie("lang", "en");
            cookie.setDomain("Your URL");
            cookie.setPath("/");
            cookie.setVersion(0);
    
            cookieManager.getCookieStore().add(new URI("https://Your URL/"), cookie);
            List<HttpCookie> Cookies =  cookieManager.getCookieStore().get(new URI("https://Your URL/"));
            String s = Cookies.get(0).getValue();
    
    0 讨论(0)
  • 2020-12-08 04:58

    You can use Apache HttpClient's facilities for that.
    Here's an excerpt from CookieJar:

    CookieSpec cookieSpec = new BrowserCompatSpec();
    
    List<Cookie> parseCookies(URI uri, List<String> cookieHeaders) {
        ArrayList<Cookie> cookies = new ArrayList<Cookie>();
        int port = (uri.getPort() < 0) ? 80 : uri.getPort();
        boolean secure = "https".equals(uri.getScheme());
        CookieOrigin origin = new CookieOrigin(uri.getHost(), port,
                uri.getPath(), secure);
        for (String cookieHeader : cookieHeaders) {
            BasicHeader header = new BasicHeader(SM.SET_COOKIE, cookieHeader);
            try {
                cookies.addAll(cookieSpec.parse(header, origin));
            } catch (MalformedCookieException e) {
                L.d(e);
            }
        }
        return cookies;
    }
    
    0 讨论(0)
  • 2020-12-08 05:04
            val headers = ..........
    
    
            val headerBuilder = Headers.Builder()
    
            headers?.forEach {
                val values = it.split(";")
                values.forEach { v ->
                    if (v.contains("=")) {
                        headerBuilder.add(v.replace("=", ":"))
                    }
                }
            }
    
            val headers = headerBuilder.build()
    
    0 讨论(0)
  • 2020-12-08 05:06

    Funny enough, but java.net.HttpCookie class cannot parse cookie strings with domain and/or path parts that this exact java.net.HttpCookie class has converted to strings.

    For example:

    HttpCookie newCookie = new HttpCookie("cookieName", "cookieValue");
    newCookie.setDomain("cookieDomain.com");
    newCookie.setPath("/");
    

    As this class implements neither Serializable nor Parcelable, it's tempting to store cookies as strings. So you write something like:

    saveMyCookieAsString(newCookie.toString());
    

    This statement will save the cookie in the following format:

    cookieName="cookieValue";$Path="/";$Domain="cookiedomain.com"
    

    And then you want to restore this cookie, so you get the string:

    String cookieAsString = restoreMyCookieString();
    

    and try to parse it:

    List<HttpCookie> cookiesList = HttpCookie.parse(cookieAsString);
    StringBuilder myCookieAsStringNow = new StringBuilder();
    for(HttpCookie httpCookie: cookiesList) {
        myCookieAsStringNow.append(httpCookie.toString());
    }
    

    now myCookieAsStringNow.toString(); produces

    cookieName=cookieValue
    

    Domain and path parts are just gone. The reason: parse method is case sensitive to words like "domain" and "path".
    Possible workaround: provide another toString() method like:

    public static String httpCookieToString(HttpCookie httpCookie) {
        StringBuilder result = new StringBuilder()
                .append(httpCookie.getName())
                .append("=")
                .append("\"")
                .append(httpCookie.getValue())
                .append("\"");
    
        if(!TextUtils.isEmpty(httpCookie.getDomain())) {
            result.append("; domain=")
                    .append(httpCookie.getDomain());
        }
        if(!TextUtils.isEmpty(httpCookie.getPath())){
            result.append("; path=")
                    .append(httpCookie.getPath());
        }
    
        return result.toString();
    }
    

    I find it funny (especially, for classes like java.net.HttpCookie which are aimed to be used by a lot and lot of people) and I hope it will be useful for someone.

    0 讨论(0)
  • 2020-12-08 05:08

    The advantage of Yanchenko's approach with Apache Http client is that is validates the cookies consistent with the spec based on the origin. The regular expression approach won't do that, but perhaps you don't need to.

    public class CookieUtil {
    
        public List<Cookie> parseCookieString(String cookies) {
            List<Cookie> cookieList = new ArrayList<Cookie>();
            Pattern cookiePattern = Pattern.compile("([^=]+)=([^\\;]*);?\\s?");
            Matcher matcher = cookiePattern.matcher(cookies);
            while (matcher.find()) {
                int groupCount = matcher.groupCount();
                System.out.println("matched: " + matcher.group(0));
                for (int groupIndex = 0; groupIndex <= groupCount; ++groupIndex) {
                    System.out.println("group[" + groupIndex + "]=" + matcher.group(groupIndex));
                }
                String cookieKey = matcher.group(1);
                String cookieValue = matcher.group(2);
                Cookie cookie = new BasicClientCookie(cookieKey, cookieValue);
                cookieList.add(cookie);
            }
            return cookieList;
        }
    }
    

    I've attached a small example using yanchenkos regex. It needs to be tweaked just a little. Without the '?' quantity modifer on the trailing ';' the trailing attribute for any cookie will not be matched. After that, if you care about the other attributes you can use Doug's code, properly encapsulated, to parse the other match groups.

    Edit: Also, note '*' qualifier on the value of the cookie itself. Values are optional and you can get cookies like "de=", i.e. no value at all. Looking at the regex again, I don't think it will handle the secure and discard cookie attributes which do not have an '='.

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