The session problem of cookie s in WK WebView and UIWebView

Posted by josh_mcqueen on Tue, 16 Jul 2019 23:46:10 +0200

Preface

First, this article describes only the Session field in cookie s.

The Session object I understand is the configuration information needed to store specific user sessions. When a user jumps over a Web page, Session will not be lost, it will always exist. When a user requests to a Web page, if the user does not have a session, the server automatically creates one, which is stored in a cookie.

The problem I encountered in my development is that some H5 businesses need to verify login before they can be used, and a special cookie field is needed to represent the source. This requires that Session be maintained in WebView, otherwise without Session, the server needs to validate user information once at a time.

WKWebView

At first I used WK WebView, which was a lot more efficient, but it was really a pit in cookie.

Cookies are not automatically saved to the NSHTTP Cookie Storage after loading, that is to say, when requests are made, they are not automatically loaded with the Cookie stored in the NSHTTP Cookie Storage container, and there is no need for the UIWebView set of memory at all. Maybe you have your own private storage (not very clear).

stay Here As you can see, you can use the same WKProcessPool instance to make different WKWebView s have the same Cookie.

/**
Build a case to save WKProcessPool
*/
+ (instancetype)shareInstance{
    static WKProcesspoolManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[WKProcesspoolManager alloc] init];
    });
    return instance;
}

- (instancetype)init {
    self.wkProcessPool = [[WKProcessPool alloc] init];
}

After this attempt, I found that I still could not solve the problem of session retention in different WKWebViews, so I wanted to see what fields Cookie saved in WKWebView.

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{

    NSHTTPURLResponse * response = (NSHTTPURLResponse *)navigationResponse.response;
    NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:response.allHeaderFields forURL:[NSURL URLWithString:_urlStr]];
    for (NSHTTPCookie *cookie in cookies) {
        NSLog(@"cookie = %@",cookie);
    }
    decisionHandler(WKNavigationResponsePolicyAllow);
}

When I got Cookie, I found that I could only get the fields I set when I asked for them. There is nothing else at all. The Sessionid Cookie may have been set by the server with the HttpOnly property, which is protected by WKWebView. So JS is impossible to modify it. Only through the WKWebView interface, but I did not find such an interface. So I have to switch back to UIWebView.

UIWebView

In return, everything is very simple.
Cookies are saved in NSHTTP Cookie Storage after requests in UIWebView, and session ID also exists.

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSHTTPCookieStorage *myCookie = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    for (NSHTTPCookie *cookie in [myCookie cookies]) {
        NSLog(@"%@", cookie);
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
    }
}

This saves the entire Cookie for automatic login. The next step is to set the saved cookies in the request.

NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL
URLWithString:HOST]]; // HOST is the domain name address of your web server
  // Setting header
for (NSHTTPCookie *cookie in cookies){
      // The cookies WithResponseHeaderFields method needs to set a cookie for the URL as a header of NSDictionary type. Note that forKey in NSDictionary needs to be @ "Set-Cookie"
     NSString *str = [[NSString alloc] initWithFormat:@"%@=%@",[cookie name],[cookie value]];
     NSDictionary *dic = [NSDictionary dictionaryWithObject:str forKey:@"Set-Cookie"];
     NSArray *headeringCookie = [NSHTTPCookie cookiesWithResponseHeaderFields:dic forURL:[NSURL URLWithString:HOST]];
     // Setting up Cookie automatically attaches the set header whenever you visit a Web page whose URL is HOST
     [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:headeringCookie
                                                        forURL:[NSURL URLWithString:HOST]
                                               mainDocumentURL:nil];
 }

This allows you to share the same session ID in different UIWebView s.

Last

After switching back to UIWebView, I tested it. Set session ID on the first page


UIWebView writes session ID


Then the second page reads the session id, which is readable.


UIWebView reads session ID

Then I used the WK WebView test to find that it was still not available.


WKWebView writes session ID

WKWebView reads session ID

I also thought that Weixin's WebView kernel seemed to be all WK WebView, so I opened the Weixin and tested it, and found that session ID could be obtained unexpectedly.


Open and write session ID in micro-message

Open and read session ID in micro-message

That is to say, Wechat has done it. Sure enough, there are ways. It's just that I'm not good enough. I hope Daniel can give me a little help, and I hope this article can help people in need.

Topics: Session Web Server