WKWebView Cookie共享 OC JS互相调用

2018-12-22  本文已影响66人  TeeMo_Yan

WKWebView的Cookie共享在项目中用法为下面3个步骤

注:WKCookieManager单利 在下面Demo中

1.  //注入 JS 代码块,解决跨域丢失问题

   WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];

    WKUserContentController *contoller = [[WKUserContentController alloc] init];

    [contolleraddUserScript:[[WKCookieManager shareManager] futhureCookieScript]];

    configuration.userContentController= contoller;

2.  //拼接同步到 NSHTTPCookieStorage 中的 Cookei

    [self.webView loadRequest:[[WKCookieManager shareManager]cookieAppendRequest:@"http://www.baidu.com"]];

3.  //防止新的跳转 cooki 丢失问题

在WKNavigationDelegate的方法中调用 

  [[WKCookieManager shareManager] fixNewRequestCookieWithRequest:navigationAction.request];

- (void)webView:(WKWebView*)webView decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction decisionHandler:(void(^)(WKNavigationActionPolicy))decisionHandler {

    [[WKCookieManager shareManager] fixNewRequestCookieWithRequest:navigationAction.request];

    decisionHandler(WKNavigationActionPolicyAllow);

}

通过Charles青花瓷抓包来查看Cookie 是否设置成功。注意清除缓存

JS调用OC  

 //方法注入

// window.webkit.messageHandlers..postMessage() for all  前端要这样写,页面退出前需要移除

    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"JSSendMessageToOC"];

- (void)viewDidDisappear:(BOOL)animated{

    [superviewDidDisappear:animated];

    //必须移除 否则VC不释放

    [self.webView.configuration.userContentController  removeScriptMessageHandlerForName:@"JSSendMessageToOC"];

}

#pragma mark - WKScriptMessageHandler

- (void)userContentController:(WKUserContentController*)userContentController didReceiveScriptMessage:(WKScriptMessage*)message{

    NSLog(@"%@---%@",message.name,message.body);

    //  第一个参数为f方法名(自行和前端协商格式)

    NSDictionary*dic = message.body;

    NSString*common_mothed = dic.allKeys.firstObject;

    //注入的公共方法

    if(![message.nameisEqualToString:@"JSSendMessageToOC"]) {

        return;

    }

    if([common_mothedisEqualToString:@"XXX"]) {

    }

}

OC 调用JS

- (void)ocSendMessageToJs:(NSString*)method parameter:(NSString*)para{

    NSString *jsStr2 = [NSString stringWithFormat:@"%@(%@)",method,para];

    [self.webView evaluateJavaScript:jsStr2 completionHandler:^(id _Nullable result, NSError * _Nullable error) {

        NSLog(@"%@----%@",result, error);

    }];

}

Demo 示例:

说明:

1.在ViewController中加载了一个UIWebview ,通过设置Cookie模拟登录后拿到的Cookie (真实开发中可忽略)

加载时,我通过Charles 抓包(此时还未点击登录成功设置Cookie按钮)结果如下

未点击设置Cookie

2.点击了跳转WKWebView ,来看下WKWebview的Cookie

未设置WKWebview的Cookie

3.然后返回,点击登录成功设置Cookie ,然后刷新UIWebVIew,通过Charles 查看UIWebView的Cookie

发现多了一个我们自己设置的TeeMo_Cookie_WebView

已经设置UIWebView的Cookie

4.点击跳转WKWebView ,通过Charles 查看WKWebView的Cookie

已经设置WKWebView的Cookie

此时都有Cookie了,我们返回,然后再进去,发现WKWebView的Cookie依然存在。


核心代码

/*

 拼接同步到 NSHTTPCookieStorage 中的 Cookei, 第一次尝试如何让 URL 刚开始加载是带上自己的 Cookie,可以通过抓包工具查看。

 @paramurl 要加载的URL

 @return拼接了 Cookie 字段后的请求

 */

- (NSURLRequest*)cookieAppendRequest:(NSString*)url{

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];

    NSArray *cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies;

    //Cookies数组转换为requestHeaderFields

    NSDictionary *requestHeaderFields = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];

    //设置请求头

    request.allHTTPHeaderFields= requestHeaderFields;

    NSLog(@"%@",request.allHTTPHeaderFields);

    return request;

}

/**

 跨域请求丢失问题

 @return注入的 JS 代码块

 */

- (WKUserScript*)futhureCookieScript{

    WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource:[self cookieString] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];

    return cookieScript;

}

- (NSString*)cookieString

{

    NSMutableString *script = [NSMutableString string];

    [scriptappendString:@"var cookieNames = document.cookie.split('; ').map(function(cookie) { return cookie.split('=')[0] } );\n"];

    for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {

        if ([cookie.value rangeOfString:@"'"].location != NSNotFound) {

            continue;

        }

        [scriptappendFormat:@"if (cookieNames.indexOf('%@') == -1) { document.cookie='%@'; };\n", cookie.name, cookie.kc_formatCookieString];

    }

    return script;

}

/**

 解决新的跳转 Cookie 丢失问题

 @paramoriginalRequest 拦截的请求

 @return带上 Cookie 的请求

 */

- (NSURLRequest*)fixNewRequestCookieWithRequest:(NSURLRequest*)originalRequest{

    NSMutableURLRequest *fixedRequest;

    if ([originalRequest isKindOfClass:[NSMutableURLRequest class]]) {

        fixedRequest = (NSMutableURLRequest*)originalRequest;

    }else{

        fixedRequest = originalRequest.mutableCopy;

    }

    NSDictionary *dict = [NSHTTPCookie requestHeaderFieldsWithCookies:[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies];

    if(dict.count) {

        NSMutableDictionary *mDict = originalRequest.allHTTPHeaderFields.mutableCopy;

        [mDictsetValuesForKeysWithDictionary:dict];

        fixedRequest.allHTTPHeaderFields= mDict;

    }

    return fixedRequest;

}

Demo :https://github.com/TeeMoYan/TMWKWebViewDemo.git

上一篇下一篇

猜你喜欢

热点阅读