Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从JavaFX网络视图访问所有cookie_Java_Cookies_Javafx_Webview - Fatal编程技术网

从JavaFX网络视图访问所有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

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

我认为只有两种解决方案,对吗

  • 实现我自己的CookieManager
  • 使用反射访问CookieManager的内部
我有什么遗漏吗

实现我自己的CookieManager绝非易事。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());
}
正如你所看到的,有很多重复,我无法访问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...
});