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只支持同域设置
         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;
}

备忘:iframe通过src加载会触发decidePolicyForNavigationAction代理;每个frame都有自己的window对象,无论是mainframe还是iframe。

2、html加载问题-同域重定向302

html资源加载一般是不会去判断登录态的,WKWebView在加载同域名的第一个html文件时,没有带cookie信息,所以直接在加载html的时重定向去判断登录态就会有问题。

解决方案:在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];
}

3、WK页面重定向-跨域cookie问题

第一个请求是www.domainA.com,接着页面302跳转到www.domainB.com,这个时候www.domainB.com这个请求就可能因为没有携带cookie而无法访问。

解决方案1:对比跳转URL与页面URL的host,如果为跨域,通过WKUserScript在注入cookie信息(document.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同时配置了根域名和子域名的cookie

现象:页面请求时,所有的cookie-name都复制多了一份,出现同个cookie-name双份的现象。

解决方案:只需要配置根域名的cookies,去掉子域名的cookies配置。

6、WK中iframe的JSBridge调用问题

WKWebView添加JSBridge的API-addScriptMessageHandler支持所有frames,包括mainframe和iframe。

在IOS端add一个JSBridge,H5页面不同的frame会挂载不同的JSBridge(window.webkit.messageHandlers.JSBridge)。

7、WKWebView哪些坑

滑动验证页面

/* 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();
    }
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
iOS中,可以通过WKWebView与JavaScript进行交互传值。以下是一些常见的方法: 1. 使用JavaScriptCore框架:在iOS 7及以上版本中,可以使用JavaScriptCore框架来实现WKWebView与JS的交互传值。具体实现步骤如下: (1)在iOS中创建一个JSContext实例,通过该实例可以操作JS环境。 (2)将JSContext实例设置到WKWebView的配置对象中。 (3)在JS中调用iOS方法时,可以通过window.webkit.messageHandlers对象进行调用,例如window.webkit.messageHandlers.methodName.postMessage(params)。 (4)在iOS中,可以通过WKScriptMessageHandler代理方法来接收JS传递的消息,并进行处理。 2. 使用WKScriptMessageHandler协议:在iOS 8及以上版本中,可以通过WKScriptMessageHandler协议来实现WKWebView与JS的交互传值。具体实现步骤如下: (1)在WKWebView的配置对象中设置WKUserContentController的代理对象,并添加需要监听的JS方法名。 (2)在JS中调用iOS方法时,可以通过window.webkit.messageHandlers对象进行调用,例如window.webkit.messageHandlers.methodName.postMessage(params)。 (3)在iOS中,可以通过WKScriptMessageHandler代理方法来接收JS传递的消息,并进行处理。 无论使用哪种方法,都需要注意JS和iOS之间传递的数据类型和格式。通常,JS传递的是字符串类型的数据,在iOS中需要进行解析和转换。同时,为了避免安全问题,需要对JS传递的数据进行校验和过滤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值