从JavaFX网络视图访问所有cookie
我需要从JavaFXWebView访问所有cookies。据我所知,有一个com.sun.webkit实现了自己的CookieManager、Cookie等。在该实现中,Cookie被隐藏起来,无法访问它们 我认为只有两种解决方案,对吗从JavaFX网络视图访问所有cookie,java,cookies,javafx,webview,Java,Cookies,Javafx,Webview,我需要从JavaFXWebView访问所有cookies。据我所知,有一个com.sun.webkit实现了自己的CookieManager、Cookie等。在该实现中,Cookie被隐藏起来,无法访问它们 我认为只有两种解决方案,对吗 实现我自己的CookieManager 使用反射访问CookieManager的内部 我有什么遗漏吗 实现我自己的CookieManager绝非易事。webkit的代码超过1500行 使用反射访问内部是非常可怕的。到目前为止,我成功地将cookie转储到JS
- 实现我自己的CookieManager
- 使用反射访问CookieManager的内部
private void saveCookies() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException, ClassNotFoundException, IOException {
CookieManager cookieManager = (CookieManager) CookieHandler.getDefault();
Field f = cookieManager.getClass().getDeclaredField("store");
f.setAccessible(true);
Object cookieStore = f.get(cookieManager);
Field bucketsField = Class.forName("com.sun.webkit.network.CookieStore").getDeclaredField("buckets");
bucketsField.setAccessible(true);
Map buckets = (Map) bucketsField.get(cookieStore);
f.setAccessible(true);
Map<String, Collection> cookiesToSave = new HashMap<>();
for (Object o : buckets.entrySet()) {
Map.Entry pair = (Map.Entry) o;
String domain = (String) pair.getKey();
Map cookies = (Map) pair.getValue();
cookiesToSave.put(domain, cookies.values());
}
Gson gson = new GsonBuilder().create();
String json = gson.toJson(cookiesToSave);
System.out.println(json);
Files.write(Paths.get("cookies.json"), json.getBytes());
}
正如你所看到的,有很多重复,我无法访问cookie的很多原始信息。在这种情况下,应该只有一个cookie(我认为)看起来像这样:
package sample;
import com.sun.webkit.network.CookieManager;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.CookieHandler;
import java.net.URI;
import java.util.*;
public class MyCookieManager extends CookieHandler {
private final CookieManager cookieManager = new CookieManager();
private final Set<URI> uris = new HashSet<>();
MyCookieManager() {
}
@Override
public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) throws IOException {
uris.add(uri);
return cookieManager.get(uri, requestHeaders);
}
@Override
public void put(URI uri, Map<String, List<String>> responseHeaders) throws IOException {
uris.add(uri);
cookieManager.put(uri, responseHeaders);
}
void save() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
System.out.println("Saving cookies");
System.out.println(uris);
for (URI uri : uris) {
System.out.println(uri);
System.out.println(cookieManager.get(uri, new HashMap<>()));
}
}
}
{
"google.co.uk": [
{
"name": "NID",
"value": "110\u003dZVaVkKbDxN3aQJYtBTWUQ9G5yc4pGb4TpB4EmTJA9bUB2a27ukBdWh28arRI52lw2Tt9hTtXxLhuWFQl55JaQXUJ3hwQzAFXKI0FB-RCU67MmgvCj9wxgqs9yg7BzBCo",
"expiryTime": 1519255457000,
"domain": "google.co.uk",
"path": "/",
"creationTime": {
"baseTime": 1503444256974,
"subtime": 0
},
"lastAccessTime": 1503444257350,
"persistent": true,
"hostOnly": false,
"secureOnly": false,
"httpOnly": true
}
]
}
据我所知,java中没有直接的方法,但您可以与网页的javascript端进行通信,这意味着您可以执行以下操作:(未经测试!) 是的,这意味着您对coockie访问有通常的限制,就像在javascript中一样。但对你来说可能就足够了 编辑: 显然,使用java.net库也是可能的(例如。
java.net.CoockieHandler.getDefault()
)。在这里,您可以找到更多关于如何使用它的信息,下面是。(在做了一些研究后更新…)
Java对CookieHandler
的默认实现是Java.net.CookieManager
,它提供了我认为您需要的API和功能(由CookieStore
和HttpCookie
类支持)。稍微参考一下这些行之间的内容,似乎java.net.CookieManager
支持一个过时的标准(RFC 2965),因此,JavaFX团队将其替换为一个非公共API类,该类(我假设)支持后来的RFC 6265。私有API实现,com.sun.webkit.network.CookieManager
不是java.net.CookieManager
的子类,并且不提供对任何其他java.net
支持类的访问。还请注意,直接使用该类中的任何API都会阻止您在任何时候更新到Java9
所以我认为你有两个选择。如果您可以使用符合RFC2965的实现,那么您所需要做的就是恢复到java.net.CookieManager
实现:只需调用
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
实例化WebView
后。然后,您可以使用标准API访问Cookie的详细信息:
cookieManager.getCookieStore().getCookies().forEach(cookie -> {
String name = cookie.getName();
String value = cookie.getValue();
String domain = cookie.getDomain();
long maxAge = cookie.getMaxAge(); // seconds
boolean secure = cookie.getSecure();
// etc...
});
请注意,HttpCookie
类定义了一个匹配算法来确定特定主机是否是特定域的一部分,因此它可以避免在属于同一域的多个URI上复制cookie
如果您需要最新的标准,那么似乎您必须对非公共类进行一些相当肮脏的黑客攻击,或者您需要实现自己的cookie处理程序(正如您所观察到的,这不是一项简单的任务)。我需要获取所有cookie,而不仅仅是当前文档的cookie。@Pablo我更新了我的答案。我不知道
java.net
的coockie管理器有多可靠,尽管你最好实现自己的coockie管理器。JavaFXs webview不使用java.net的cookie管理器,它使用com.sun.webkit的cookie管理器。我目前不在桌面上,因此很难检查实现情况等。。我是基于链接的SO帖子(这是针对javafx2的,所以在此期间它可能确实发生了变化)做出这个假设的。在SO post中有一个小的snippit,您可以轻松测试它。如果这不起作用,那么我就失去了想法,这很不幸。@Pablo我认为com.sun.webkit.CookieManager
是默认的实现,无论您使用的是JavaFX还是普通的旧Java。如果您知道所有相关的URI,您可以通过默认的cookie处理程序通过URI获取cookie。这就足够了吗,或者你需要通过编程的方式找出为其设置cookie的URI吗?我需要通过编程的方式获取所有cookie。我不会拥有所有的URI。因此我认为您必须实现自己的CookieHandler
。这可能还不算太糟:您可能只需要包装默认实现并将两个抽象方法转发给它;只需修饰put
实现,使其将所有URI
存储在一个集合中。无可否认,我没有尝试过:)@James_D:我可以这样做,但是我该如何处理uri集?uri集将告诉您存储cookie的所有uri。因此,您可以对它们进行迭代,并为每一个调用cookieHandler.get(uri,new HashMap())
。
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
cookieManager.getCookieStore().getCookies().forEach(cookie -> {
String name = cookie.getName();
String value = cookie.getValue();
String domain = cookie.getDomain();
long maxAge = cookie.getMaxAge(); // seconds
boolean secure = cookie.getSecure();
// etc...
});