
我认为只有两种解决方案是正确的:
>实现我自己的CookieManager
>使用反射访问CookieManager的内部
我在这里错过了什么吗?
实现我自己的CookieManager并非易事. com.sun.webkit是超过1500行代码.
使用反射访问内部是非常可怕的.到目前为止,我设法将cookie转储到JSON文件,但查看代码:
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());
}
在@James_D评论之后,我尝试为CookieManager创建一个包装器,如下所示:
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后,当我调用save时,我得到了这个:
https://ssl.gstatic.com/gb/images/b_8d5afc09.png
{}
https://www.google.co.uk/images/branding/googlelogo/1x/googlelogo_white_background_color_272x92dp.png
{Cookie=[NID=110=TnISuEnlryFjSzvLgWXIuTBRDx_CTBlgPOqFzCPXM88M0xQY_1nSJEG2uyCxk-RFNbdexuen5A_3CZXHevseXhRSKJmRSHis0pUb4kvFCxliWT8RsKvRXoAxBYJhGGd2]}
https://www.google.co.uk/client_204?&atyp=i&biw=500&bih=455&ei=Q72cWa_IJ4KhUc6xpqAH
{Cookie=[NID=110=TnISuEnlryFjSzvLgWXIuTBRDx_CTBlgPOqFzCPXM88M0xQY_1nSJEG2uyCxk-RFNbdexuen5A_3CZXHevseXhRSKJmRSHis0pUb4kvFCxliWT8RsKvRXoAxBYJhGGd2]}
https://clients1.google.co.uk/generate_204
{Cookie=[NID=110=TnISuEnlryFjSzvLgWXIuTBRDx_CTBlgPOqFzCPXM88M0xQY_1nSJEG2uyCxk-RFNbdexuen5A_3CZXHevseXhRSKJmRSHis0pUb4kvFCxliWT8RsKvRXoAxBYJhGGd2]}
https://www.google.co.uk/xjs/_/js/k=xjs.hp.en_US.HWKnNOqE224.O/m=sb_he,d/am=ABg/rt=j/d=1/t=zcms/rs=ACT90oFd7WTU33BO8_uKNZdqfket_iKTeg
{Cookie=[NID=110=TnISuEnlryFjSzvLgWXIuTBRDx_CTBlgPOqFzCPXM88M0xQY_1nSJEG2uyCxk-RFNbdexuen5A_3CZXHevseXhRSKJmRSHis0pUb4kvFCxliWT8RsKvRXoAxBYJhGGd2]}
https://google.com/
{}
https://www.google.co.uk/?gfe_rd=cr&ei=Q72cWb30H9P38Ae7lKagCw
{Cookie=[NID=110=TnISuEnlryFjSzvLgWXIuTBRDx_CTBlgPOqFzCPXM88M0xQY_1nSJEG2uyCxk-RFNbdexuen5A_3CZXHevseXhRSKJmRSHis0pUb4kvFCxliWT8RsKvRXoAxBYJhGGd2]}
https://www.google.co.uk/images/nav_logo229.png
{Cookie=[NID=110=TnISuEnlryFjSzvLgWXIuTBRDx_CTBlgPOqFzCPXM88M0xQY_1nSJEG2uyCxk-RFNbdexuen5A_3CZXHevseXhRSKJmRSHis0pUb4kvFCxliWT8RsKvRXoAxBYJhGGd2]}
https://ssl.gstatic.com/gb/js/sem_e63c08fa6f0a34d4ef28b1bece13b39d.js
{}
你可以看到有很多重复,我无法访问cookie的许多原始信息.在这种情况下,它应该只是一个cookie(我认为),如下所示:
{
"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的默认CookieHandler实现是java.net.CookieManager,它提供了我认为你正在寻找的API和功能(由CookieStore和HttpCookie类支持).参考Setting a cookie using JavaFX’s WebEngine/WebView并稍微阅读一下,似乎java.net.CookieManager支持一个过时的标准(RFC 2965),因此,JavaFX团队用非公共API类替换它(我是假设)支持后面的RFC 6265.私有API实现com.sun.webkit.network.CookieManager不是java.net.CookieManager的子类,也不提供对任何其他java.net支持类的访问.另请注意,直接使用该类中的任何API将阻止您随时更新到Java 9.
所以我认为你有两个选择.如果您可以使用符合RFC 2965的实现,那么您需要做的就是恢复到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处理程序(正如您所观察到的那样,这不是一项简单的任务) .
转载注明原文:从JavaFX WebView访问所有cookie - 乐贴网