IOS WKWebView與Cookie問題梳理

1、WK 腳本注入Cookies信息-代碼示例

/* Ajax、iframe請求配置cookies */
- (WKWebViewConfiguration *)configuration {
    if (!_configuration) {
        _configuration = [[WKWebViewConfiguration alloc] init];
        _configuration.allowsInlineMediaPlayback = YES;
        
        if (@available(iOS 10.0, *)) {
            if ([_configuration respondsToSelector:@selector(mediaTypesRequiringUserActionForPlayback)]) {
                _configuration.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
            }
        } else if(@available(iOS 9.0, *)){
            if([_configuration respondsToSelector:@selector(setRequiresUserActionForMediaPlayback:)]) {
                _configuration.requiresUserActionForMediaPlayback = NO;
            }
        } else if([_configuration respondsToSelector:@selector(setMediaPlaybackRequiresUserAction:)]){
            _configuration.mediaPlaybackRequiresUserAction = NO;
        }
        WKUserContentController* userContentController = [[WKUserContentController alloc] init];
        _configuration.userContentController = userContentController;

       /*
         document.cookie='uid=123456;path=/;domain=.baidu.com';
         document.cookie='_DC=1;path=/;domain=.baidu.com';
         document.cookie='session=eddf8312293823dcabd903;path=/;
         domain=.baidu.com';document.cookie='os=iOS;path=/;domain=.baidu.com';
        */

        NSString *strDocumentCookie = [self getCookiesForWKWebview];
        WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource:strDocumentCookie injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        [userContentController addUserScript:cookieScript];
    }
    return _configuration;
}

2、html加載問題-同域重定向302

html資源加載一般是不會去判斷登錄態的,WKWebView在加載同域名的第一個html文件時,沒有帶cookie信息,所以直接在加載html的時重定向去判斷登錄態就會有問題。

方案1:在webView加載request前,配置cookie信息(只對該request生效-mainFrame)。

/* 配置cookie信息 */
- (void)loadRequest {
  NSMutableDictionary *cookieDic = [MKCookieManager getCookieConfig];

  NSMutableString *cookieValue = [NSMutableString stringWithFormat:@""];

  for (NSString *key in cookieDic) {
    NSString *appendString = [NSString stringWithFormat:@"%@=%@;", key, [cookieDic valueForKey:key]];
    [cookieValue appendString:appendString];
  }
    
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.strUrl]];
  if ([cookieValue isNotEmpty]) {
    [request setValue:cookieValue forHTTPHeaderField:@"Cookie"];
  }

  [self.webView loadRequest:request];
}

 方案2:在APP啓動或者重新登錄後,預加載一個同根域名的常規h5頁面(cookie更新不及時)。

/* 啓動或者登錄後 TabbarVC*/
- (void)loadRequest {
   if (self.webView) {
      [self.webView stopLoading];
      self.webView.delegate = nil;
      self.webView = nil;
   }
   MKWebView* webView = [[MKWebView alloc] initWithFrame:CGRectZero delegate:self];
   self.webView = webView;
    
   NSURLRequest* req = [NSURLRequest requestWithURL:[NSURL 
   URLWithString:@"https://host/path.html"]];
   [self.webView loadRequest:req];
}

- (NSString *)documentCookieForWKWebview {
   return [MKCookieManager documentCookieForWKWebview:[NSURL URLWithString:@"https://host/path.html"]];
}

3、WK頁面重定向-跨域cookie問題

第一個請求是www.yuminga.com,接着頁面302跳轉到www.yumingb.com,這個時候www.yumingb.com這個請求就可能因爲沒有攜帶cookie而無法訪問。

方案1:對比跳轉URL與頁面URL的host,如果爲跨域,通過WKUserScript在注入cookie信息。

/* 跨域重定向-同步cookie */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    NSString* URLString = ([self.crossDominLink isNotEmpty] ? self.crossDominLink: self.pageUrl);
    NSURL* currentURL = [NSURL URLWithString:URLString];

    if (![currentURL.host isEqualToString:navigationAction.request.URL.host]) {
        //跨域重定向注入cookieScript
        NSString *strDocumentCookie = [MKCookieManager genDocumentCookieForWKWebview:navigationAction.request.URL];
        WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource:strDocumentCookie injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
        [webView.configuration.userContentController  addUserScript:cookieScript];

        self.crossDominLink = navigationAction.request.URL.absoluteString;
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

方案2:對比跳轉URL與頁面URL的host,如果爲跨域且未做處理,攔截該跳轉,重新配置request的cookie信息,再loadRequest一下。(只適合加載mainFrame請求,iframe無效)

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    NSURL* currentURL = [NSURL URLWithString:self.pageUrl];
    
    if ((![self.crossDomainURL isEqualToString:navigationAction.request.URL.absoluteString]) && (![currentURL.host isEqualToString:navigationAction.request.URL.host])) {

        self.crossDomainURL = navigationAction.request.URL.absoluteString;

        NSMutableURLRequest* request = [navigationAction.request mutableCopy];

        NSString* cookieValue = @"session=720bff297ea3866696380368f81fc4e4;token_id=NzIwYmZmMjk3ZWEzODY2Njk2MzgwMzY4ZjgxZmM0ZTQ=;uid=123456;";

        [request setValue:cookieValue forHTTPHeaderField:@"Cookie"];

        [webView loadRequest:request];

        decisionHandler(WKNavigationActionPolicyCancel);
    } else {
        decisionHandler(WKNavigationActionPolicyAllow);
    }
    
}

4、CookieStorage同一根域名name重複問題

現象:APP未登錄時訪問接口,客戶端沒有設置session,後端接口會回寫一個session,導致NSHTTPCookieStorage也會多出一個session。

方案:在退出登錄、重新登錄後,清除掉NSHTTPCookieStorage中與用戶相關的cookies,再進行cookies的賦值。

5、WK同時配置了根域名和url-host的cookie

現象:頁面請求時,所有的cookie-name都複製多了一份,出現同個cookie-name雙份的現象。

方案:只需要配置根域名的cookies,去掉url-host的cookies配置。

6、WKWebView哪些坑

https://www.jianshu.com/p/a9087a07f671

/* JS-alert crash容錯 */
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)())completionHandler {
    if (!self.isLoadFinish) {
        completionHandler();
        return;
    }
    
    if (self.isViewLoaded && self.view.window) {
        MKAlertView *alertView = [[MKAlertView alloc] initWithTitle:@"溫馨提示" message:message confrimTitle:@"確定" confrimCallBack:^{
            completionHandler();
        }];

        [alertView show];
    } else {
        completionHandler();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章