+-
从JavaFX WebView访问所有cookie
我需要从 JavaFX WebView访问所有cookie.据我所知,有一个com.sun.webkit实现了自己的CookieManager,Cookie等等.在该实现中,cookie被隐藏起来,无法访问它们.

我认为只有两种解决方案是正确的:

>实现我自己的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 - 乐贴网