Flutter项目中添加Webview(九)管理Cookie

1,647 阅读3分钟

你的应用可以使用CookieManager类管理WebView中的Cookie。在此步骤中,您将针对Cookie列表执行显示、清除和删除操作,还会设置新Cookie。针对每个Cookie用例向_MenuOptions添加条目。

enum _MenuOptions {
    navigationDelegate,
    userAgent,
    javascriptChannel,
    // Add from here ...
    listCookies,
    clearCookies,
    addCookie,
    setCookie,
    removeCookie,
    // .. to here.
}

此步骤中的其余更改集中在Menu类中,包括将Menu类从无状态转换为优状态。此更改很重要,因为Menu需要拥有CookieManaget,而无状态小部件中的可变状态是一种不好的组合。

将Menu类转换为StatefulWidget,然后CookieManager添加到生成State类。

class Menu extends StatefulWidget {
    const Menu({required this.controller, Key? key}) : super(key: key);
    
    final Completer<WebViewController> controller;
    
    @override
    State<Menu> createState() => _MenuState();
}

class _MenuState extendss State<Menu> {
    final CookieManager cookieManaget = CookieManager();
    
    @override
    Widget build(BuildContext context) {
        // ...
    }
}

_MenuState类将包含之前的Menu类中添加的代码以及新添加的CookieManager.

获取所有Cookie的列表

您将使用JavaScript来获取所有Cookie的列表。为此,在名为 _onListCookies_MenuState类的末尾添加一个辅助方法。使runJavaScriptReturningResult方法,辅助方法会在JavaScript环境中执行document.cookie,并返回所有的Cookie的列表

Future<void> _onListCookies(WebViewController controller) async {
    final String cookies = await controller.runJavascriptReturningResult('document.cookie');
    ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text(cookies.isNotEmpty ? cookies : 'There are no cookies.'));
    );
}

清除所有Cookie

如需清除WebView中的所有Cookie,请使用CookieManager类的clearCookies方法。如果CookieManager清除了Cookie,此方法会返回一个解析为trueFuture<bool>;如果没有要清除的Cookie,则会返回false

Future<void> _onClearCookies() async {
    final hadCookiess = await cookieManager.clearCookies();
    String message = 'There were cookies. Now, they are gone!';
    if (!hadCookies) {
        message = 'There were no cookies to clear.';
    }
    ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text(message))
    );
}

添加Cookie

可通过调用JavaScript添加Cookie。用于向JavaScript文档添加Cookie的API详细记载。

Future<void> _onAddCookie(WebViewController controller) async {
    await controller.runJavascript('''
        var data = new Date();
        date.setTime(date.getTime()+(30*24*60*60*1000));
        document.cookie = "FirstName=John; expires=" + data.toGMTString();
    ''');
    ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
        content: Text('Custom cookie added.'),
        )
    );
}

使用CookieManager设置Cookie

还可以使用CookieManager设置Cookie

Future<void> _onSetCookie(WebViewController controller) async {
    await cookieManager.setCookie(
        const WebViewCookie(name: 'foo', value: 'bar', domain: 'flutter.dev');
    );
    ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
            content: Text('Custom cookie is set.');
        ),
    );
}

移除Cookie

移除Cookie的操作是指添加一个过期日期设为过去的时间的Coookie。

Future<void> _onRemoveCookie(WebViewController controller) async {
    await controller.runJavascript(
        'document.cookie="FirstName=John; expired=Thu, 01 Jan 1970 00:00:00 UTC" '
    );
    ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
            content: Text('Custom cookie removed.'),
        ),
    );
}

添加CookieManager菜单项

剩下的任务就是添加菜单选项,并将其连接在你刚才添加的辅助方法。

class _MenuState extends State<Menu> {
    final CookieManager cookieManager = CookieManager();
    
    @override
    Widget build(BuildContext context) {
        return FutureBuilder<WebViewController>(
            future: widget.controller.future,
            builder: (context, controller) {
                onSelected: (value) async {
                    switch(value) {
                        case _MenuOptions.navigationDelegate: 
                            controller.data!.loadUrl('https://youtube.com');
                            break;
                        case _MenuOptions.userAgent:
                            final userAgent = await controller.data!.runJavascriptReturningResult('navigator.userAgent');
                            ScaffoldMessenger.of(context).showSnackBar(
                                SnackBar(content: Text(userAgent))
                            );
                            break;
                        case _MenuOption.javascriptChannel:
                            await controller.data!.runJavascript('''
                                var req = new XMLHttpRequest();
                                req.open('GET', "https://api.ipify.org/?format=json");
                                req.onload = function() {
                                    if (req.status == 200) {
                                        let response = JSON.parse(req.responseText);
                                        SnackBar.postMessage("Ip Address: " + response.ip);
                                    } else {
                                        SnackBar.postMessage("Error: " + req.status);
                                    }
                                }
                                req.send();
                            ''');
                            break;
                            // Add from here
                            case _MenuOptions.clearCookies:
                                _onClearCookies();
                                break;
                            case _MenuOptions.listCookies:
                                _onListCookies(controller.data!);
                                break;
                            case _MenuOptionss.addCookie:
                                _onAddCookie(controller.data!);
                                break;
                            case _MenuOptioons.setCookie:
                                _onSetCookie(controller.data!);
                                break;
                            case _MenuOptions.removeCookie:
                                _onRemoveCookie(controller.data!);
                                break;
                            // ... to here
                    }
                },
                itemBuilder: (context) => [
                    const PopupMenuItem<_MenuOptions>(
                        value: _MenuOptions.navigationDelegate,
                        child: Text('Navigate to Youtube'),
                    ),
                    const PopupMenuItem<_MenuOptions>(
                        value: _MenuOptions,userAgent,
                        child: Text('Show user-agent'),
                    ),
                    const PopupMenuItem<_MenuOptions>(
                        value: _MenuOptions.javascriptChannel,
                        child: Text('Lookup IP Address'),
                    ),
                    //Add from here ...
                    const PopupMenuItem<_MenuOptions>(
                        value: _MenuOptions.clearCookies,
                        child: Text('Clear cookies'),
                    ),
                    const PopupMenuItem<_MenuOptions>(
                        value: _MenuOptions.listCookies,
                        child: Text('List cookies'),
                    ),
                    const PoputMenuItem<_MenuOptions>(
                        value: _MenuOptions.addCookie,
                        child: Text('Add cookie'),
                    ),
                    const PopupMenuItem<_MenuOptions>(
                        valie: _MenuOptions.setCookie,
                        child: Text('Set cookie'),
                    ),
                    const PopupMenuItem<_MenuOptions>(
                        value: _MenuOptions.removeCookie,
                        child: Text('Remove cookie'),
                    ),
                    // .. to here
                ],
            }
        );
    }
}

CookieManager

1、选择List cookies。系统应会列出flutter.dev设置Google Analytics Coookie。

ezgif.com-gif-maker.gif 2、选择Clear cookies,系统应会报告没有可清除的任何Cookie。

ezgif.com-gif-maker (1).gif 3、再次选择Clear cookies。系统应会报告没有金额清除的任何Cookie。

ezgif.com-gif-maker (2).gif 4、选择List cookies。系统应报告没有Cookie。

image.png 5、选择Add cookie。系统应会报告Cookie已添加。

ezgif.com-gif-maker (3).gif 6、选择Set Cookie。系统应会报告哦Cookie已设置。

ezgif.com-gif-maker (4).gif 7、选择List cookies,最后,选择Remove cookie。

ezgif.com-gif-maker (5).gif