如何解析cookie字符串

cot*_*aws 28 java string cookies android

我想要一个Cookie字符串(因为它可能在Set-Cookie标头中返回)并且能够轻松修改它的一部分,特别是到期日期.

我看到有几个不同的Cookie类,比如BasicClientCookie,但我没有看到任何简单的方法将字符串解析为其中一个对象.

我在api 9级看到他们添加了HttpCookie,它有一个解析方法,但我需要在以前的版本中工作.

有任何想法吗?

谢谢

yeg*_*256 96

怎么样java.net.HttpCookie:

List<HttpCookie> cookies = HttpCookie.parse(header);
Run Code Online (Sandbox Code Playgroud)

  • @MattWolfe正确,但在2009年发现此问题的人中有90%不再担心API 9.这就是为什么现在这个答案正在被褒奖. (8认同)
  • 此方法无法解析正确的Cookie ...请勿使用它! (5认同)
  • 失败的值如下:`SSID PHPSESSID = d6cb3d4a5e6fd3bbe5078f37d616fac1; 路径= /,ci_session = a%3A0%3A%7B%7D; expires = Mon,10-Nov-2014 12:37:06 GMT; 最大年龄= -31500000; 路径= /,ci_session = a%3A5%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%22ca963cd5e9b6d9631c5afc8f26eb7374%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A14%3A%22182.59. 202.107%22%3BS%3A10%3A%22user_agent%22%3BS%3A60%3A%22Dalvik%2F2.1.0 +%28Linux%3B + U%3B +的Android + 5.1.1%3B +的Nexus + 5 +构建%2FLMY48B %29%22%3BS%3A13%3A%22last_activity%22%3Bi%3A144712​​3026%3BS%3A9%3A%22user_data%22%3Bs` (4认同)
  • 这是OP所指的,直到api 9才可用. (3认同)
  • @用户3:您发布的饼干违反[RFC 2109§4.1](https://tools.ietf.org/html/rfc2109#section-4.1)读取_token(非正式) - 非特殊序列,非-white space characters_,所以`SSID PHPSESSID`不应该包含空格.@atasoyh:很高兴看到一个具体的例子...... (3认同)

Dou*_*aul 12

我相信你必须手动解析它.试试这个:

BasicClientCookie parseRawCookie(String rawCookie) throws Exception {
    String[] rawCookieParams = rawCookie.split(";");

    String[] rawCookieNameAndValue = rawCookieParams[0].split("=");
    if (rawCookieNameAndValue.length != 2) {
        throw new Exception("Invalid cookie: missing name and value.");
    }

    String cookieName = rawCookieNameAndValue[0].trim();
    String cookieValue = rawCookieNameAndValue[1].trim();
    BasicClientCookie cookie = new BasicClientCookie(cookieName, cookieValue);
    for (int i = 1; i < rawCookieParams.length; i++) {
        String rawCookieParamNameAndValue[] = rawCookieParams[i].trim().split("=");

        String paramName = rawCookieParamNameAndValue[0].trim();

        if (paramName.equalsIgnoreCase("secure")) {
            cookie.setSecure(true);
        } else {
            if (rawCookieParamNameAndValue.length != 2) {
                throw new Exception("Invalid cookie: attribute not a flag or missing value.");
            }

            String paramValue = rawCookieParamNameAndValue[1].trim();

            if (paramName.equalsIgnoreCase("expires")) {
                Date expiryDate = DateFormat.getDateTimeInstance(DateFormat.FULL)
                        .parse(paramValue);
                cookie.setExpiryDate(expiryDate);
            } else if (paramName.equalsIgnoreCase("max-age")) {
                long maxAge = Long.parseLong(paramValue);
                Date expiryDate = new Date(System.getCurrentTimeMillis() + maxAge);
                cookie.setExpiryDate(expiryDate);
            } else if (paramName.equalsIgnoreCase("domain")) {
                cookie.setDomain(paramValue);
            } else if (paramName.equalsIgnoreCase("path")) {
                cookie.setPath(paramValue);
            } else if (paramName.equalsIgnoreCase("comment")) {
                cookie.setPath(paramValue);
            } else {
                throw new Exception("Invalid cookie: invalid attribute name.");
            }
        }
    }

    return cookie;
}
Run Code Online (Sandbox Code Playgroud)

我实际上没有编译或运行此代码,但它应该是一个强大的开始.你可能不得不把日期解析一下:我不确定cookie中使用的日期格式实际上和DateFormat.FULL.(查看这个相关问题,其中涉及处理cookie中的日期格式.)另外,请注意,有一些cookie属性未被BasicClientCookie诸如version和处理httponly.

最后,这段代码假设cookie的名称和值显示为第一个属性:我不确定这是否一定是真的,但这就是我见过的每个cookie的订购方式.


yan*_*nko 8

您可以使用Apache HttpClient的工具.
这是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;
}
Run Code Online (Sandbox Code Playgroud)


Vit*_*nko 7

有趣的是,java.net.HttpCookie类不能使用域和/或路径部分解析cookie字符串,而这些部分java.net.HttpCookie已经转换为字符串.

例如:

HttpCookie newCookie = new HttpCookie("cookieName", "cookieValue");
newCookie.setDomain("cookieDomain.com");
newCookie.setPath("/");
Run Code Online (Sandbox Code Playgroud)

由于此类既不实现Serializable也不实现Parcelable,因此将cookie存储为字符串很诱人.所以你写了类似的东西:

saveMyCookieAsString(newCookie.toString());
Run Code Online (Sandbox Code Playgroud)

此语句将以以下格式保存cookie:

cookieName="cookieValue";$Path="/";$Domain="cookiedomain.com"
Run Code Online (Sandbox Code Playgroud)

然后你想要恢复这个cookie,所以你得到了字符串:

String cookieAsString = restoreMyCookieString();
Run Code Online (Sandbox Code Playgroud)

并尝试解析它:

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

现在myCookieAsStringNow.toString();生产

cookieName=cookieValue
Run Code Online (Sandbox Code Playgroud)

域和路径部分刚刚消失.原因是:解析方法对"域"和"路径"之类的单词区分大小写.
可能的解决方法:提供另一个toString()方法,如:

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();
}
Run Code Online (Sandbox Code Playgroud)

我发现它很有趣(特别是对于java.net.HttpCookie那些旨在被很多人使用的课程而言),我希望它对某些人有用.

  • 看来,`HttpCookie`将cookie解析为服务器cookie,但将其字符串化为用户代理cookie –也许是因为[它的JavaDoc](https://docs.oracle.com/javase/8/docs/api/ java / net / HttpCookie.html)读取:_在服务器和用户agent_之间传送状态信息。另请参见[RFC 2109的示例部分](https://tools.ietf.org/html/rfc2109#section-5)。 (2认同)

kre*_*rco 6

使用正则表达式:

([^=]+)=([^\;]+);\s?
Run Code Online (Sandbox Code Playgroud)

你可以像这样解析一个cookie:

.COOKIEAUTH=5DEF0BF530F749AD46F652BDF31C372526A42FEB9D40162167CB39C4D43FC8AF1C4B6DF0C24ECB1945DFF7952C70FDA1E4AF12C1803F9D089E78348C4B41802279897807F85905D6B6D2D42896BA2A267E9F564814631B4B31EE41A483C886B14B5A1E76FD264FB230E87877CB9A4A2A7BDB0B0101BC2C1AF3A029CC54EE4FBC; 
expires=Sat, 30-Jul-2011 01:22:34 GMT; 
path=/; HttpOnly
Run Code Online (Sandbox Code Playgroud)

在几行代码中.