我想获取一个Cookie字符串(因为它可能会在Set-Cookie标头中返回)并且能够轻松修改部分字符串,特别是到期日期。
我看到有几个不同的Cookie类,比如BasicClientCookie,但我没有看到任何简单的方法将字符串解析为其中一个对象。
我在api级别9中看到他们添加了HttpCookie,它有一个解析方法,但我需要在以前的版本中使用一些东西。
有什么想法吗?
由于
答案 0 :(得分:90)
List<HttpCookie> cookies = HttpCookie.parse(header);
答案 1 :(得分:11)
我相信你必须手动解析它。试试这个:
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;
}
我实际上没有编译或运行此代码,但它应该是一个强大的开始。你可能不得不把日期解析一下:我不确定cookie中使用的日期格式实际上与DateFormat.FULL
相同。 (查看this相关问题,该问题涉及处理Cookie中的日期格式。)另请注意,BasicClientCookie
无法处理某些Cookie属性,例如version
和{{1} }。
最后,这段代码假设cookie的名称和值显示为第一个属性:我不确定这是否一定是真的,但这就是我见过的每个cookie的订购方式。
答案 2 :(得分: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;
}
答案 3 :(得分:7)
很有趣,但是ImplicitlyUnwrappedOptional
类无法使用域和/或路径部分解析cookie字符串,而这些部分已经转换为字符串。{/ p>
例如:
func someGlobalFunction() -> String! { return nil }
class MyClass {
let aVariable: String
init() {
aVariable = someGlobalFunction()
}
}
由于此类既不实现Serializable也不实现Parcelable,因此将cookie存储为字符串很诱人。所以你写了类似的东西:
java.net.HttpCookie
此语句将以以下格式保存cookie:
java.net.HttpCookie
然后你想恢复这个cookie,所以你得到了字符串:
HttpCookie newCookie = new HttpCookie("cookieName", "cookieValue");
newCookie.setDomain("cookieDomain.com");
newCookie.setPath("/");
并尝试解析它:
saveMyCookieAsString(newCookie.toString());
现在cookieName="cookieValue";$Path="/";$Domain="cookiedomain.com"
生成
String cookieAsString = restoreMyCookieString();
域名和路径部分只是消失。原因是:解析方法对“域”和“路径”之类的单词区分大小写。
可能的解决方法:提供另一个toString()方法,如:
List<HttpCookie> cookiesList = HttpCookie.parse(cookieAsString);
StringBuilder myCookieAsStringNow = new StringBuilder();
for(HttpCookie httpCookie: cookiesList) {
myCookieAsStringNow.append(httpCookie.toString());
}
我发现它很有趣(特别是像myCookieAsStringNow.toString();
这样的课程,目的是被很多人使用)我希望它对某些人有用。
答案 4 :(得分:6)
使用正则表达式:
([^=]+)=([^\;]+);\s?
你可以像这样解析一个cookie:
.COOKIEAUTH=5DEF0BF530F749AD46F652BDF31C372526A42FEB9D40162167CB39C4D43FC8AF1C4B6DF0C24ECB1945DFF7952C70FDA1E4AF12C1803F9D089E78348C4B41802279897807F85905D6B6D2D42896BA2A267E9F564814631B4B31EE41A483C886B14B5A1E76FD264FB230E87877CB9A4A2A7BDB0B0101BC2C1AF3A029CC54EE4FBC;
expires=Sat, 30-Jul-2011 01:22:34 GMT;
path=/; HttpOnly
在几行代码中。
答案 5 :(得分:0)
Yanchenko使用Apache Http客户端的方法的优势在于验证与基于原点的规范一致的cookie。正则表达式方法不会那样做,但也许你不需要。
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;
}
}
我附上了一个使用yanchenkos正则表达式的小例子。它需要稍微调整一下。没有'?'尾随';'上的数量修饰任何cookie的尾随属性都不匹配。之后,如果您关心其他属性,可以使用Doug的代码(正确封装)来解析其他匹配组。
编辑:另外,请注意cookie本身值的'*'限定符。值是可选的,您可以获得像“de =”这样的cookie,即根本没有值。再看一下正则表达式,我认为它不会处理没有'='的安全和丢弃cookie属性。
答案 6 :(得分:0)
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();
答案 7 :(得分:0)
如果您碰巧安装了Netty HTTP编解码器,还可以使用io.netty.handler.codec.http.cookie.ServerCookieDecoder.LAX|STRICT
。很方便。
答案 8 :(得分:-1)
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()