从JavaFX WebView访问所有cookie [英] Access all the cookies from a JavaFX WebView

查看:1379
本文介绍了从JavaFX WebView访问所有cookie的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to access all the cookies from a JavaFX WebView. As far as I can see there's a com.sun.webkit that implements its own CookieManager, Cookie, etc, etc. In that implementation, the cookies are hidden away and there's no way to access them.

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

Am I correct in thinking there are only two solutions:


  • 实施我自己的CookieManager

  • 使用反射来访问CookieManager的内部结构

我在这里遗漏了什么吗?

Am I missing anything here?

实现我自己的CookieManager并非易事。 com.sun.webkit是超过1500行代码。

Implementing my own CookieManager is no trivial task. com.sun.webkit's is more than 1500 lines of code.

使用反射访问内部是非常可怕的。到目前为止,我设法将cookie转储到JSON文件,但查看代码:

Using reflection to access the internals is quite horrible. So far, I managed to dump the cookies to a JSON file but look at the code:

 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创建一个包装器,就像这样:

Following @James_D comments, I tried making a wrapper for CookieManager, something like this:

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后,当我打电话保存,我明白了:

After accessing Google, when I call save, I get this:

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(我认为)看起来像这样:

As you can see there's a lot of repetition and I don't have access to a lot of the original information of the cookie. In this case, it should be just one cookie (I think) that looks like this:

{
  "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
    }
  ]
}


推荐答案

(做了一些研究后更新......)

(Updated after doing some research...)

Java的默认实现 CookieHandler java.net.CookieManager ,它提供API和功能我认为你正在寻找(由 CookieStore HttpCookie 类支持)。参考使用JavaFX的WebEngine / WebView设置cookie 并在看起来 java.net.CookieManager 支持一个过时的标准(RFC 2965),正因为如此,JavaFX团队用非公开的方式取而代之 - 我假设的API类支持更高版本的RFC 6265.私有API实现 com.sun.webkit.network.CookieManager 不是<$ c的子类$ c> java.net.CookieManager 并且不提供对任何其他 java.net 支持类的访问权限。另请注意,直接使用该类中的任何API将阻止您随时更新到Java 9.

Java's default implementation of CookieHandler is java.net.CookieManager, which provides the API and functionality I think you are looking for (supported by the CookieStore and HttpCookie classes). Referring to Setting a cookie using JavaFX's WebEngine/WebView and reading between the lines a little, it seems that java.net.CookieManager supports an obsolete standard (RFC 2965), and because of that, the JavaFX team replaced it with a non-public-API class that (I am assuming) supports the later RFC 6265. The private-API implementation, com.sun.webkit.network.CookieManager is not a subclass of java.net.CookieManager and doesn't provide access to any of the other java.net supporting classes. Note also that using any of the API from that class directly will prevent you updating to Java 9 at any point.

所以我认为您有两个选择。如果您可以使用符合RFC 2965的实现,那么您需要做的就是恢复到 java.net.CookieManager 实现:只需调用

So I think you have two choices. If you can live with a RFC 2965-compliant implementation, all you need to do is to revert to the java.net.CookieManager implementation: just call

CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);

实例化 WebView后。然后,您可以使用标准API访问Cookie的详细信息:

after instantiating the WebView. Then you can use the standard API to access details of the cookies:

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。

Note that the HttpCookie class defines a matching algorithm to determine if a particular host is part of a particular domain, so it avoids replicating cookies over multiple URIs belonging to the same domain.

如果您需要更新的标准,那么你似乎要么必须对非公开的类做一些相当肮脏的黑客攻击,要么你需要实现自己的cookie处理程序(正如你所观察到的那样,这不是一项微不足道的任务)。

If you need the more recent standard, then it seems you either have to do some fairly dirty hacking on the non-public classes, or you need to implement your own cookie handler (which as you've observed, is not a trivial task).

这篇关于从JavaFX WebView访问所有cookie的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆