Shared Cookies with Wkprocesspool for Wkwebview in Swift

Cookies Sharing between wkwebviews

Try the following code in your loadView() for both of your ViewController classes:

webConfiguration.processPool = viewHome.processPool

override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webConfiguration.processPool = viewHome.processPool
webViewHome = WKWebView(frame: .zero, configuration: webConfiguration)

Additional:For standard, please Use the camel case in the Class name convention (viewHome -> ViewHome).

Cookie sharing between multiple WKWebViews

Got this working by using the same WKProcessPool for all the webviews.

First create a process pool once somewhere:

processPool = [[WKProcessPool alloc] init];

Then use it when creating WKWebviews. The pool must be set in the init method, not afterwards.

WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.processPool = processPool;
webview = [[WKWebView alloc] initWithFrame:frame configuration:config];

WKWebViews (multiple) - sharing cookies, localStorage in Swift

I think it is best if you use SFSafariViewController for your needs.

As the documentation states:

In iOS 9 and 10, it shares cookies and other website data with Safari.

It means, that it is going to use the same cookies and data from the Safari browser, which is even better. If I am not mistaken, the user can be logged in through Safari, and when he comes to your app, he will not have to log in again.

Here is the full documentation for it:

SFSafariViewController

Update:

If you still want to do what you already started, according to this answer here in Objective-C, this is the solution in Swift:

You need a place where you would store the persistent 'process pool'. In your case, it is YourModelObject singleton

class YourModelObject {
static let sharedInstance = YourModelObject()
let processPool = WKProcessPool()
}

Use the shared processPool before initializing the webView. This is the initialization function which you would call in the loadView() for every viewController:

override func loadView() {
super.loadView() //don't forget this line

setupWebView()
}

private func setupWebView() {

let config = WKWebViewConfiguration()
config.processPool = YourModelObject.sharedInstance.processPool
self.webView = WKWebView(frame: .zero, configuration: config)
self.webView.navigationDelegate = self
self.webView.scrollView.delegate = self
self.view = self.webView
}

Getting all cookies from WKWebView

Finally, httpCookieStore for WKWebsiteDataStore landed in iOS 11.

https://developer.apple.com/documentation/webkit/wkwebsitedatastore?changes=latest_minor

Swift persistent cookie storage

To share all new cookies between multiple webviews you can use WKProcessPool so just create the single pool for your app and set it to your webviews:

let ProcessPool = WKProcessPool()
...
let configuration = WKWebViewConfiguration()
configuration.processPool = ProcessPool
webView = WKWebView(frame: self.view.bounds, configuration: configuration)

If you want to be notified about changes with cookies you should add an observer to WKWebsiteDataStore before creating your webviews:

WKWebsiteDataStore.default().httpCookieStore.add(self)

...

extension AppDelegate : WKHTTPCookieStoreObserver {
func cookiesDidChange(in cookieStore: WKHTTPCookieStore) {
cookieStore.getAllCookies { cookies in
print(cookies)
}
}
}

By default all cookies from webviews are stored between your app's launches.

WKWebView Persistent Storage of Cookies

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

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 NSHTTPCookieStorage to find them. People suggest 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.

One last thing in general: I said that your success might also depend on the type of cookie. That's because this answer states 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.

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...).

Use shared WKWebViewCookies for a request

1) If your cookies are not HTTP-only, you can get them by evaluating JavaScript command document.cookie on webView and use them for your request.
If they are HTTP-only, it seems that there is no working method to do this.
There is no documented way to sync cookies between WKWebView and NSURLSession as far as I know.

2) Another approach (if cookies belong to same domain which REST API belongs) - create "background" webView with same process pool and perform all operations to REST API via this instance - cookies will be added automatically (even HTTP-only):

  1. You can set any params (method/body/headers/etc) to request and load
    it via loadRequest:; If your REST API returns JSON, you can use JavaScript command
    document.body to get it;

  2. Getting response code a little bit harder - you need to implement
    webView:decidePolicyForNavigationResponse: method of
    WKNavigationDelegate and catch
    it.

  3. Also, you need to keep in mind that you can perform only 1 request
    in webView simultaneously. So, you may need to create some queue
    of requests that will be performed one after another.



Related Topics



Leave a reply



Submit