ios WKWebView 持久存储 Cookie

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39772007/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 10:24:57  来源:igfitidea点击:

WKWebView Persistent Storage of Cookies

ioscookieswkwebview

提问by haplo1384

I am using a WKWebViewin my native iPhone application, on a website that allows login/registration, and stores the session information in cookies. I am trying to figure out how to persistently store the cookie information, so when the app restarts, the user still has their web session available.

WKWebView在我的本机 iPhone 应用程序中使用了一个允许登录/注册的网站,并将会话信息存储在 cookie 中。我试图弄清楚如何持久存储 cookie 信息,以便当应用程序重新启动时,用户仍然可以使用他们的网络会话。

I have 2 WKWebViewsin the app, and they share a WKProcessPool. I start with a shared process pool:

WKWebViews在应用程序中有 2 个,它们共享一个WKProcessPool. 我从共享进程池开始:

WKProcessPool *processPool = [[WKProcessPool alloc] init];

WKProcessPool *processPool = [[WKProcessPool alloc] init];

Then for each WKWebView:

然后对于每个 WKWebView:

WKWebViewConfiguration *theConfiguration = [[WKWebViewConfiguration alloc] init]; 
theConfiguration.processPool = processPool; 
self.webView = [[WKWebView alloc] initWithFrame:frame configuration:theConfiguration];

When I log in using the first WKWebView, and then some time later pass the action to the 2nd WKWebView, the session is retained, so the cookies were successfully shared. However, when I relaunch the app, a new process pool is created and the session information is destroyed. Is there any way to get the session information to persist through an app restart?

当我使用第一个登录WKWebView,然后一段时间后将操作传递给 2nd 时WKWebView,会话被保留,因此 cookie 成功共享。但是,当我重新启动应用程序时,会创建一个新的进程池并销毁会话信息。有没有办法让会话信息通过应用程序重新启动而持久化?

采纳答案by Gero

This is actually a tough one because there's a) some bugthat's still not solved by Apple (I think) and b) depends on what cookies you want, I think.

这实际上是一个艰难的过程,因为 a) Apple 仍然没有解决一些错误(我认为)和 b) 取决于你想要什么 cookie,我认为。

I wasn't able to test this now, but I can give you some pointers:

我现在无法测试这个,但我可以给你一些提示:

  1. Getting cookies from NSHTTPCookieStorage.sharedHTTPCookieStorage(). This one seems buggy, apparently the cookies aren't immediately saved for NSHTTPCookieStorageto find them. Peoplesuggest to trigger a save by resetting the process pool, but I don't know whether that reliably works. You might want to try that out for yourself, though.
  2. The process pool is not really what saves the cookies (though it defines whether they are shared as you correctly stated). The documentation says that's WKWebsiteDataStore, so I'd look that up. At least getting the cookies from there using fetchDataRecordsOfTypes:completionHandler:might be possible (not sure how to set them, though, and I assume you can't just save the store in user defaults for the same reason as for the process pool).
  3. Should you manage to get the cookies you need (or rather their values), but not be able to restore them as I guess will be the case, look here(basically it shows how to simply prepare the httprequest with them already, relevant part: [request addValue:@"TeskCookieKey1=TeskCookieValue1;TeskCookieKey2=TeskCookieValue2;" forHTTPHeaderField:@"Cookie"]).
  4. If all else fails, check this. I know providing just link only answers is not good, but I can't copy all that and just want to add it for completeness sake.
  1. NSHTTPCookieStorage.sharedHTTPCookieStorage(). 这个看起来有问题,显然 cookie 没有立即保存NSHTTPCookieStorage以便找到它们。人们建议通过重置进程池来触发保存,但我不知道这是否可靠。不过,您可能想亲自尝试一下。
  2. 进程池并不是真正保存 cookie 的东西(尽管它定义了它们是否如您正确所述的那样共享)。文档说那是WKWebsiteDataStore,所以我会查一下。至少可以使用从那里获取 cookie fetchDataRecordsOfTypes:completionHandler:(虽然不确定如何设置它们,但我假设您不能出于与进程池相同的原因将存储保存在用户默认值中)。
  3. 如果您设法获得所需的 cookie(或者更确切地说是它们的值),但无法像我猜的那样恢复它们,请看这里(基本上它显示了如何简单地使用它们准备 httprequest,相关部分:[request addValue:@"TeskCookieKey1=TeskCookieValue1;TeskCookieKey2=TeskCookieValue2;" forHTTPHeaderField:@"Cookie"])。
  4. 如果所有其他方法都失败了,请检查这个。我知道只提供链接答案并不好,但我不能复制所有这些,只是为了完整起见想添加它。

One last thing in general: I said that your success might also depend on the type of cookie. That's because this answerstates that cookies set by the server are not accessible via NSHTTPCookieStorage. I don't know whether that's relevant to you (but I guess it is, since you're probably looking for a session, i.e. server-set cookie, correct?) and I don't know whether this means that the other methods fail as well.

最后一件事:我说过,您的成功可能还取决于 cookie 的类型。那是因为这个答案指出服务器设置的 cookie 不能通过NSHTTPCookieStorage. 我不知道这是否与您相关(但我猜是这样,因为您可能正在寻找会话,即服务器设置的 cookie,对吗?)而且我不知道这是否意味着其他方法失败以及。

If all else fails, you might consider saving the users credentials somewhere (keychain, for example) and reuse them on the next app start to auth automatically. This might not restore all session data, but considering the user quit the app that's maybe actually desirable? Also perhaps certain values can be caught and saved for later use using an injected script, like mentioned here(obviously not for setting them at start, but maybe retrieve them at some point. You need to know how the site works then, of course).

如果所有其他方法都失败了,您可以考虑将用户凭据保存在某处(例如钥匙串),并在下一个应用程序开始自动进行身份验证时重用它们。这可能不会恢复所有会话数据,但考虑到用户退出可能实际上是可取的应用程序?此外,也许可以使用注入的脚本捕获并保存某些值以供以后使用,就像这里提到的一样(显然不是在开始时设置它们,但可能在某个时候检索它们。当然,您需要知道该站点是如何工作的) .

I hope that could at least point you towards some new directions solving the issue. It's not as trivial as it should be, it seems (then again, session cookies are kind of a security relevant thing, so maybe hiding them away from the App is a conscious design choice by Apple...).

我希望这至少可以为您指明解决问题的一些新方向。看起来它并不像它应该的那样微不足道(再说一次,会话 cookie 是一种与安全相关的东西,所以也许将它们隐藏在应用程序之外是 Apple 有意识的设计选择......)。

回答by Harish Pathak

After days of research and experiments, I have found a solution to manage sessions in WKWebView, This is a work around because I didn't find any other way to achieve this, below are the steps:

经过几天的研究和实验,我找到了一个在 WKWebView 中管理会话的解决方案,这是一个解决方法,因为我没有找到任何其他方法来实现这一点,以下是步骤:

First you need to create methods to set and get data in user defaults, when I say data it means NSData, here are the methods.

首先你需要创建方法来设置和获取用户默认值中的数据,当我说数据时,它意味着 NSData,这里是方法。

+(void)saveDataInNSDefault:(id)object key:(NSString *)key{
    NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:object];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:encodedObject forKey:key];
    [defaults synchronize];
}

+ (id)getDataFromNSDefaultWithKey:(NSString *)key{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *encodedObject = [defaults objectForKey:key];
    id object = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject];
    return object;
}

For maintaining session on webview I made my webview and WKProcessPool singleton.

为了在 webview 上维护会话,我制作了 webview 和 WKProcessPool 单例。

- (WKWebView *)sharedWebView {
    static WKWebView *singleton;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        WKWebViewConfiguration *webViewConfig = [[WKWebViewConfiguration alloc] init];
        WKUserContentController *controller = [[WKUserContentController alloc] init];

        [controller addScriptMessageHandler:self name:@"callNativeAction"];
        [controller addScriptMessageHandler:self name:@"callNativeActionWithArgs"];
        webViewConfig.userContentController = controller;
        webViewConfig.processPool = [self sharedWebViewPool];

        singleton = [[WKWebView alloc] initWithFrame:self.vwContentView.frame configuration:webViewConfig];

    });
    return singleton;
}

- (WKProcessPool *)sharedWebViewPool {
    static WKProcessPool *pool;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        pool = [Helper getDataFromNSDefaultWithKey:@"pool"];

        if (!pool) {
            pool = [[WKProcessPool alloc] init];
        }

    });
    return pool;
}

In ViewDidLoad, I check if it's not the login page and load cookies into HttpCookieStore from User Defaults so It will by pass authentication or use those cookies to maintain session.

在 ViewDidLoad 中,我检查它是否不是登录页面,并将 cookie 从用户默认值加载到 HttpCookieStore 中,以便通过身份验证或使用这些 cookie 来维护会话。

if (!isLoginPage) {
            [request setValue:accessToken forHTTPHeaderField:@"Authorization"];

            NSMutableSet *setOfCookies = [Helper getDataFromNSDefaultWithKey:@"cookies"];
            for (NSHTTPCookie *cookie in setOfCookies) {
                if (@available(iOS 11.0, *)) {

                    [webView.configuration.websiteDataStore.httpCookieStore setCookie:cookie completionHandler:^{}];
                } else {
                    // Fallback on earlier versions
                    [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
                }
            }
        }

And, Load the request.

并且,加载请求。

Now, we will maintain webview sessions using cookies, so on your login page webview, save cookies from httpCookieStore into user defaults in viewDidDisappear method.

现在,我们将使用 cookie 维护 webview 会话,因此在您的登录页面 webview 上,将 httpCookieStore 中的 cookie 保存到 viewDidDisappear 方法中的用户默认值中。

- (void)viewDidDisappear:(BOOL)animated {

    if (isLoginPage) { //checking if it's login page.
        NSMutableSet *setOfCookies = [Helper getDataFromNSDefaultWithKey:@"cookies"]?[Helper getDataFromNSDefaultWithKey:@"cookies"]:[NSMutableArray array];
        //Delete cookies if >50
        if (setOfCookies.count>50) {
            [setOfCookies removeAllObjects];
        }
        if (@available(iOS 11.0, *)) {
            [webView.configuration.websiteDataStore.httpCookieStore getAllCookies:^(NSArray<NSHTTPCookie *> * _Nonnull arrCookies) {

                for (NSHTTPCookie *cookie in arrCookies) {
                    NSLog(@"Cookie: \n%@ \n\n", cookie);
                    [setOfCookies addObject:cookie];
                }
                [Helper saveDataInNSDefault:setOfCookies key:@"cookies"];
            }];
        } else {
            // Fallback on earlier versions
            NSArray *cookieStore = NSHTTPCookieStorage.sharedHTTPCookieStorage.cookies;
            for (NSHTTPCookie *cookie in cookieStore) {
                NSLog(@"Cookie: \n%@ \n\n", cookie);
                [setOfCookies addObject:cookie];
            }
            [Helper saveDataInNSDefault:setOfCookies key:@"cookies"];
        }
    }

    [Helper saveDataInNSDefault:[self sharedWebViewPool] key:@"pool"];
}

Note: Above method is tested for iOS 11 only, although I have written fallback for lower versions also but didn't test those.

注意:上述方法仅针对 iOS 11 进行了测试,虽然我也为较低版本编写了后备但没有测试这些。

Hope this solves your problems !!! :)

希望这能解决你的问题!!!:)

回答by jarora

I'm a little late in answering this but I would like to add some insights to the existing answers. The answer already mentioned herealready provides valuable information into Cookie Persistence on WKWebView. There are a few caveats though.

我回答这个问题有点晚了,但我想为现有答案添加一些见解。这里已经提到的答案已经为 WKWebView 上的 Cookie 持久性提供了有价值的信息。不过有一些注意事项。

  1. WKWebViewdoesn't work well with NSHTTPCookieStorage, so for iOS 8, 9, 10 you will have to use UIWebView.
  2. You don't need to necessarily hold on to the WKWebViewas a singleton but you do need to use the same instance of WKProcessPoolevery time to get the desired cookies again.
  3. It is preferable to set the cookies first using the setCookiemethod and then instantiate the WKWebView.
  1. WKWebView不适NSHTTPCookieStorage用于 ,因此对于 iOS 8、9、10,您将不得不使用 UIWebView。
  2. 您不一定需要将 保持WKWebView为单例,但您确实需要WKProcessPool每次都使用相同的实例 来再次获取所需的 cookie。
  3. 最好先使用setCookie方法设置 cookie ,然后实例化WKWebView.

I would also like to highlight the iOS 11+ Solution in Swift.

我还想重点介绍 Swift 中的 iOS 11+ 解决方案。

let urlString = "http://127.0.0.1:8080"
var webView: WKWebView!
let group = DispatchGroup()

override func viewDidLoad() {
    super.viewDidLoad()
    self.setupWebView { [weak self] in
        self?.loadURL()
    }
}

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    if #available(iOS 11.0, *) {
        self.webView.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in
            self.setData(cookies, key: "cookies")
        }
    } else {
        // Fallback on earlier versions
    }
}

private func loadURL() {
    let urlRequest = URLRequest(url: URL(string: urlString)!)
    self.webView.load(urlRequest)
}

private func setupWebView(_ completion: @escaping () -> Void) {

    func setup(config: WKWebViewConfiguration) {
        self.webView = WKWebView(frame: CGRect.zero, configuration: config)
        self.webView.navigationDelegate = self
        self.webView.uiDelegate = self
        self.webView.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(self.webView)

        NSLayoutConstraint.activate([
            self.webView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
            self.webView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
            self.webView.topAnchor.constraint(equalTo: self.view.topAnchor),
            self.webView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor)])
    }

    self.configurationForWebView { config in
        setup(config: config)
        completion()
    }

}

private func configurationForWebView(_ completion: @escaping (WKWebViewConfiguration) -> Void) {

    let configuration = WKWebViewConfiguration()

    //Need to reuse the same process pool to achieve cookie persistence
    let processPool: WKProcessPool

    if let pool: WKProcessPool = self.getData(key: "pool")  {
        processPool = pool
    }
    else {
        processPool = WKProcessPool()
        self.setData(processPool, key: "pool")
    }

    configuration.processPool = processPool

    if let cookies: [HTTPCookie] = self.getData(key: "cookies") {

        for cookie in cookies {

            if #available(iOS 11.0, *) {
                group.enter()
                configuration.websiteDataStore.httpCookieStore.setCookie(cookie) {
                    print("Set cookie = \(cookie) with name = \(cookie.name)")
                    self.group.leave()
                }
            } else {
                // Fallback on earlier versions
            }
        }

    }

    group.notify(queue: DispatchQueue.main) {
        completion(configuration)
    }
}

Helper methods:

辅助方法:

func setData(_ value: Any, key: String) {
    let ud = UserDefaults.standard
    let archivedPool = NSKeyedArchiver.archivedData(withRootObject: value)
    ud.set(archivedPool, forKey: key)
}

func getData<T>(key: String) -> T? {
    let ud = UserDefaults.standard
    if let val = ud.value(forKey: key) as? Data,
        let obj = NSKeyedUnarchiver.unarchiveObject(with: val) as? T {
        return obj
    }

    return nil
}

Edit: I had mentioned that it's preferable to instantiate WKWebViewpost setCookiecalls. I ran into some issues wherein the setCookiecompletion handlers were not getting called the second time I tried to open the WKWebView. This seems to a be a bug in the WebKit. Therefore, I had to instantiate WKWebViewfirst and then call setCookieon the configuration. Make sure to load the URL only after all the setCookiecalls have returned.

编辑:我曾提到最好实例化WKWebView后期setCookie调用。我遇到了一些问题,其中setCookie第二次尝试打开WKWebView. 这似乎是 WebKit 中的一个错误。因此,我必须先实例化WKWebView,然后调用setCookie配置。确保仅在所有setCookie调用返回后才加载 URL 。

回答by Dovydas Rup?ys

I am a bit late to the party but people might find this useful. There is a workaround, it's a bit annoying but as far as I can say it is the only solution that works reliably, at least until apple fix their dumb APIs...

我参加聚会有点晚了,但人们可能会发现这很有用。有一个解决方法,它有点烦人,但据我所知,它是唯一可靠工作的解决方案,至少在苹果修复他们愚蠢的 API 之前......

I've spend a good 3 days trying to get the cached cookies out of the WKWebViewneedless to say that got me nowhere... eventually I've released that I could just get the cookies directly from the server.

我已经花了 3 天的时间来尝试获取缓存的 cookie,WKWebView不用说这让我无处可去……最终我发布了我可以直接从服务器获取 cookie 的消息。

The first thing I tried to do is get all the cookies with javascript that was running within the WKWebViewand then pass them to the WKUserContentControllerwhere I would just store them to UserDefaults. This didn't work since my cookies where httponlyand apparently you can't get those with javascript...

我试图做的第一件事是让所有的JavaScript这是内运行的饼干WKWebView,然后将它们传递到WKUserContentController哪里,我只想他们存储UserDefaults。这是行不通的,因为我的 cookie 在哪里httponly并且显然您无法使用 javascript 获取那些...

I've ended up fixing it by inserting a javascript call into the page on the server side (Ruby on Rail in my case) with the cookies as the parameter, e.g.

我最终通过将 javascript 调用插入到服务器端的页面(在我的例子中是 Ruby on Rail)以 cookie 作为参数来修复它,例如

sendToDevice("key:value")

sendToDevice("key:value")

The above js function is simply passing cookies to the device. Hope this will help someone stay sane...

上面的 js 函数只是简单地将 cookie 传递给设备。希望这会帮助某人保持理智......

回答by Tumata

After extensive search and manual debug I reached these simple conclusions (iOS11+).

经过广泛的搜索和手动调试,我得出了这些简单的结论(iOS11+)。

You need to considerate these two categories:

你需要考虑这两个类别:

  • You are using WKWebsiteDataStore.nonPersistentDataStore:

    Then the WKProcessPooldoes not matter.

    1. Extract cookies using websiteDataStore.httpCookieStore.getAllCookies()
    2. Save these cookies into UserDefaults (or preferably the Keychain).
    3. ...
    4. Later when you re-create these cookies from storage, call websiteDataStore.httpCookieStore.setCookie()for each cookie and you're good to go.
  • You are using WKWebsiteDataStore.defaultDataStore:

    Then the WKProcessPoolassociated with configuration DOES matter. It has to be saved along with the cookies.

    1. Save the webview configuration's processPool into UserDefaults (or preferably the Keychain).
    2. Extract cookies using websiteDataStore.httpCookieStore.getAllCookies()
    3. Save these cookies into UserDefaults (or preferably the Keychain).
    4. ...
    5. Later re-create the process pool from storage and assign it to the web view's configuration
    6. Re-create the cookies from storage and call websiteDataStore.httpCookieStore.setCookie()for each cookie
  • 您正在使用WKWebsiteDataStore.nonPersistentDataStore

    那就WKProcessPool无所谓了

    1. 使用提取 cookie websiteDataStore.httpCookieStore.getAllCookies()
    2. 将这些 cookie 保存到 UserDefaults(或者最好是钥匙串)中。
    3. ...
    4. 稍后当您从存储中重新创建这些 cookie 时,调用websiteDataStore.httpCookieStore.setCookie()每个 cookie 就可以了。
  • 您正在使用WKWebsiteDataStore.defaultDataStore

    然后WKProcessPool与配置相关的事情很重要。它必须与 cookie 一起保存。

    1. 将 webview 配置的 processPool 保存到 UserDefaults(或者最好是 Keychain)。
    2. 使用提取 cookie websiteDataStore.httpCookieStore.getAllCookies()
    3. 将这些 cookie 保存到 UserDefaults(或者最好是钥匙串)中。
    4. ...
    5. 稍后从存储重新创建进程池并将其分配给 web 视图的配置
    6. 从存储中重新创建 cookie 并调用websiteDataStore.httpCookieStore.setCookie()每个 cookie

Note: there are many detailed implementations already available so I keep it simple by not adding more implementation details.

注意:已经有许多详细的实现可用,所以我不会添加更多的实现细节来保持简单。

回答by wj2061

WKWebViewconforms to NSCoding,so you can use NSCoderto decode/encode your webView ,and store it somewhere else ,like NSUserDefaults.

WKWebView符合NSCoding,所以你可以NSCoder用来解码/编码你的 webView,并将它存储在其他地方,比如NSUserDefaults.

//return data to store somewhere
NSData* data = [NSKeyedArchiver archivedDataWithRootObject:self.webView];/

self.webView = [NSKeyedUnarchiver unarchiveObjectWithData:data];

回答by Moussa Ndour

Finally, I have found a solution to manage sessions in WKWebView, work under swift 4, but the solution can be carried to swift 3 or object-C:

最后,我找到了在WKWebView中管理会话的解决方案,在swift 4下工作,但该解决方案可以携带到swift 3或object-C:

class ViewController: UIViewController {

let url = URL(string: "https://insofttransfer.com")!


@IBOutlet weak var webview: WKWebView!

override func viewDidLoad() {

    super.viewDidLoad()
    webview.load(URLRequest(url: self.url))
    webview.uiDelegate = self
    webview.navigationDelegate = self
}}

Create an extension for WKWebview...

为 WKWebview 创建扩展...

extension WKWebView {

enum PrefKey {
    static let cookie = "cookies"
}

func writeDiskCookies(for domain: String, completion: @escaping () -> ()) {
    fetchInMemoryCookies(for: domain) { data in
        print("write data", data)
        UserDefaults.standard.setValue(data, forKey: PrefKey.cookie + domain)
        completion();
    }
}


 func loadDiskCookies(for domain: String, completion: @escaping () -> ()) {
    if let diskCookie = UserDefaults.standard.dictionary(forKey: (PrefKey.cookie + domain)){
        fetchInMemoryCookies(for: domain) { freshCookie in

            let mergedCookie = diskCookie.merging(freshCookie) { (_, new) in new }

            for (cookieName, cookieConfig) in mergedCookie {
                let cookie = cookieConfig as! Dictionary<String, Any>

                var expire : Any? = nil

                if let expireTime = cookie["Expires"] as? Double{
                    expire = Date(timeIntervalSinceNow: expireTime)
                }

                let newCookie = HTTPCookie(properties: [
                    .domain: cookie["Domain"] as Any,
                    .path: cookie["Path"] as Any,
                    .name: cookie["Name"] as Any,
                    .value: cookie["Value"] as Any,
                    .secure: cookie["Secure"] as Any,
                    .expires: expire as Any
                ])

                self.configuration.websiteDataStore.httpCookieStore.setCookie(newCookie!)
            }

            completion()
        }

    }
    else{
        completion()
    }
}

func fetchInMemoryCookies(for domain: String, completion: @escaping ([String: Any]) -> ()) {
    var cookieDict = [String: AnyObject]()
    WKWebsiteDataStore.default().httpCookieStore.getAllCookies { (cookies) in
        for cookie in cookies {
            if cookie.domain.contains(domain) {
                cookieDict[cookie.name] = cookie.properties as AnyObject?
            }
        }
        completion(cookieDict)
    }
}}

Then Create an extension for our View Controller Like this

然后像这样为我们的视图控制器创建一个扩展

extension ViewController: WKUIDelegate, WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
   //load cookie of current domain
    webView.loadDiskCookies(for: url.host!){
        decisionHandler(.allow)
    }
}

public func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
   //write cookie for current domain
    webView.writeDiskCookies(for: url.host!){
        decisionHandler(.allow)
    }
}
}

Where urlis current URL:

url当前网址在哪里:

    let url = URL(string: "https://insofttransfer.com")!

回答by Sachin Vas

Store the information in NSUserDefaults. At the same time if the session information is very critical, it is better to store it in KeyChain.

将信息存储在NSUserDefaults. 同时,如果会话信息非常关键,最好将其存储在KeyChain.