清除JavaFX WebView中的会话/缓存/cookie

ttcibm8c  于 2022-10-08  发布在  Java
关注(0)|答案(3)|浏览(379)

我有一个Swing对话框,它使用JavaFX WebView显示来自Google服务器的OAuth 2.0URL。

public class SimpleSwingBrowser extends JDialog {

    private final JFXPanel jfxPanel = new JFXPanel();
    private WebEngine engine;

    private final JPanel panel = new JPanel(new BorderLayout());

    public SimpleSwingBrowser() {
        super(MainFrame.getInstance(), JDialog.ModalityType.APPLICATION_MODAL);
        initComponents();
    }

    private void initComponents() {
        createScene();

        panel.add(jfxPanel, BorderLayout.CENTER);

        getContentPane().add(panel);

        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width-460)/2, (screenSize.height-680)/2, 460, 680);
    }

    private void createScene() {

        Platform.runLater(new Runnable() {
            @Override 
            public void run() {

                final WebView view = new WebView();
                engine = view.getEngine();

                engine.titleProperty().addListener(new ChangeListener<String>() {
                    @Override
                    public void changed(ObservableValue<? extends String> observable, String oldValue, final String newValue) {
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override 
                            public void run() {
                                SimpleSwingBrowser.this.setTitle(newValue);
                            }
                        });
                    }
                });

                engine.getLoadWorker()
                        .exceptionProperty()
                        .addListener(new ChangeListener<Throwable>() {

                            public void changed(ObservableValue<? extends Throwable> o, Throwable old, final Throwable value) {
                                if (engine.getLoadWorker().getState() == FAILED) {
                                    SwingUtilities.invokeLater(new Runnable() {
                                        @Override public void run() {
                                            JOptionPane.showMessageDialog(
                                                    panel,
                                                    (value != null) ?
                                                    engine.getLocation() + "n" + value.getMessage() :
                                                    engine.getLocation() + "nUnexpected error.",
                                                    "Loading error...",
                                                    JOptionPane.ERROR_MESSAGE);
                                        }
                                    });
                                }
                            }
                        });

                // http://stackoverflow.com/questions/11206942/how-to-hide-scrollbars-in-the-javafx-webview
                // hide webview scrollbars whenever they appear.
                view.getChildrenUnmodifiable().addListener(new ListChangeListener<Node>() {
                    @Override 
                    public void onChanged(Change<? extends Node> change) {
                        Set<Node> deadSeaScrolls = view.lookupAll(".scroll-bar");
                        for (Node scroll : deadSeaScrolls) {
                            scroll.setVisible(false);
                        }
                    }
                });

                jfxPanel.setScene(new Scene(view));
            }
        });
    }

    public void loadURL(final String url) {
        Platform.runLater(new Runnable() {
            @Override 
            public void run() {
                String tmp = toURL(url);

                if (tmp == null) {
                    tmp = toURL("http://" + url);
                }

                engine.load(tmp);
            }
        });
    }

    private static String toURL(String str) {
        try {
            return new URL(str).toExternalForm();
        } catch (MalformedURLException exception) {
                return null;
        }
    }
}

每次,我都会从谷歌获得以下URL。我将使用SimpleSwingBrowser加载以下URL。

https://accounts.google.com/o/oauth2/auth?client_id=xxx&redirect_uri=http://localhost:55780/Callback&response_type=code&scope=email%20https://www.googleapis.com/auth/drive.appdata%20profile

第一次中,将会显示如下界面。

第一屏

第二屏

在我

1.在第一屏登录成功。
1.展示第二屏。
1.点击接受。
1.关闭Web浏览器对话框。
1.同样,生成与第一次完全相同的URL。
1.创建一个全新的SimpleSwingBrowser示例,加载步骤中生成的URL

我预计谷歌会再次向我展示第一个屏幕,因为这是一个新的浏览会。然而,我第二次看到的是第二屏。

看起来,WebView中有一些存储的会话/缓存/cookie,尽管它是一个全新的示例。

我预计我会回到第一屏,这样我就可以支持多个用户帐户。

如何清除WebView中的会话/缓存/cookie?

9gm1akwq

9gm1akwq1#

JavaFX WebView的会话Cookie存储在java.net.CookieHandler中。

要自行管理Cookie,请创建java.net.CookieManager的新示例:

java.net.CookieManager manager = new java.net.CookieManager();

然后将其设置为默认:

java.net.CookieHandler.setDefault(manager);

要清除Cookie,只需调用emoveAll方法:

manager.getCookieStore().removeAll();

或者只需创建Cookie管理器的新示例并将其设置为默认:

java.net.CookieHandler.setDefault(new java.net.CookieManager());
bqf10yzr

bqf10yzr2#

我使用了JavaFX 8 WebView来显示来自Google和Dropbox的OAuth 2.0。事实证明,将java.net.CookieManager()的新示例设置为默认设置在Google上有效(当然还删除了会话cookie),但我再也无法使用我的Dropbox帐户登录了。“登录”按钮就是不起作用。

我进行了调试,发现默认情况下使用的是com.sun.webkit.network.CookieManager示例。所以,我用了

java.net.CookieHandler.setDefault(new com.sun.webkit.network.CookieManager());

这解决了我的问题。由于它的javadoc,它与RFC 6265兼容,这是HTTP Cookie和Set-Cookie头字段的当前定义。

由于JRE中的一些访问限制,您需要使用JDK(不仅仅是JRE)作为项目的系统库。

tcbh2hod

tcbh2hod3#

我只是想发布关于JavaFX18的WebView当前状态的更新,因为我们使用了建议的解决方案(在调用Web视图之前设置Cookie管理器),但仍然存在问题。

这是因为WebEngine中用于发出请求的HTTP2Loader类的工作方式:

// Use singleton instance of HttpClient to get the maximum benefits
@SuppressWarnings("removal")
private final static HttpClient HTTP_CLIENT =
    AccessController.doPrivileged((PrivilegedAction<HttpClient>) () -> HttpClient.newBuilder()
            .version(Version.HTTP_2)  // this is the default
            .followRedirects(Redirect.NEVER) // WebCore handles redirection
            .connectTimeout(Duration.ofSeconds(30)) // FIXME: Add a property to control the timeout
            .cookieHandler(CookieHandler.getDefault())
            .build());

因为HTTP_CLIENT字段是static并用于执行请求,所以只有在第一次创建HTTP2Loader示例时,才会引用当前的默认CookieHandler。因此,如果您每次都在通过WebView加载页面之前设置一个新的CookieHandler,那么这将只起作用一次。此后,HTTP_CLIENT单例将始终使用创建时引用的CookieHandler

这是HTTP2Loader类中的一个设计问题。该字段应为非静态字段,而不是static字段。无论如何,HTTP2Loader类实际上是一个不变的一次性使用示例,因此不需要使用单例来执行请求。

我真的不知道他们为什么会采用这个解决方案。即使是javadoc也没有多大意义,因为它的“好处”是什么?

因此,现在有两种解决方案:

1.访问当前的Cookie处理程序,并为您要访问的URI放置一个空Map。例如CookieHandler.getDefault().put(someUri, Collections.emptyMap()),但如果您访问一个端,并且在此过程中发生了大量重定向,则这将是一个问题,在这种情况下,没有办法知道应该清空哪些URI cookie。
1.在第一次加载任何WebView中的页面之前创建一个新的CookieHandler,并跟踪它。然后,在再次加载WebView之前,清除您跟踪的处理程序的CookieStore。

话虽如此,如果您无法控制的另一段代码执行以下操作,则上述方法将失败:

  • 注意到当前默认的CookieHandler
  • 设置新的默认CookieHandler
  • 首次创建WebView并加载页面
  • 再次将旧的CookieHandler设置为默认

在这种情况下,您将永远无法再次访问CookieHandler,即从那里开始在WebView中使用。

相关问题