WKWebView 设置Cookie

作者: 广锅锅 | 来源:发表于2017-03-20 15:14 被阅读199次

    WKWebView本来是有设置cookie的api的,具体做法如下

    // 创建一个WKUserScript,设置好cookie
    WKUserScript *cookieScript = [[WKUserScript alloc] initWithSource:@"document.cookie='name=Zhang;age=28;'" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
    // webView 执行这个Script
    [webView.configuration.userContentController addUserScript:cookieScript];
    

    结果如何呢?等网页加载出来后,在web检查器中看一下存储空间
    不知道怎么打开web检查器的:首先保证你的手机开了web检查器选项,设置>Safari>高级>web检查器,然后手机连上电脑,在电脑端的Safari选择开发>你的手机名>右边就是webView列表>选择想要查看的页面

    WKUserScript 设置cookie的结果
    看到这里,可以看到,一条语句虽然设置两个cookie,但只有一条生效,age=18找不到。算了,没有就分开设置,一条一条设也是可以的。
    正准备拍拍手,打完收工?且慢!后台有『茬』要找了,后台说,我根本没有看到cookie啊!
    你说,怎么可能,苹果爸爸做的东西怎么会有问题,一定是你们的问题。
    被后台『找茬』多次后,我们来抓包看看吧,还是一样的程序,还是一样的代码,结果如下
    程序发出的请求中cookie列表
    阿勒!仔细对比下,除了自己设置的cookie一条没有,其他的cookie一条不少。
    这是为什么呢?踩了一年WKWebView的坑,我想我可以解释下,WKUserScript,从名字来看,这根本就不是专门设置cookie的啊,它是用来注入本地js脚本的,不只是cookie,其他的js方法啊什么的都可以用它来注入。
    而这个类的初始化方法中有个时间参数WKUserScriptInjectionTime,这是个枚举有两个值.......AtDocumentStart...end,从名字中可以看出,这分别是在html的Document文档开始加载加载结束时注入js。也就是说,这个方法设置cookie的过程是在数据已经下载完成,在本地解析过程中设置的,后台完全看不到啊。是的,后台找你那么多『茬』真的是你的错。

    当初完全没想到这其中的原因,我也不知道怎么解决。那时,我也就听从了我们后台的方案:

    1. 在发起的request请求头里面,手动设置所有的cookie,包括自己要加的、NSHTTPCookieStorage里面本来有的,这是为了后台能拿到cookie。
    2. 发起request请求。
    3. 在收到网页数据时,把之前发送的那些cookie字符串,手动的在webview里面再执行一次,这是为了web本地能拿到cookie。

    具体的代码如下

    // 1. 先添加cookie到String
    NSMutableString *cookieString = [NSMutableString stringWithFormat:@"name=zhang;(这里面的分号千万不要忘记)"]; 
    
    // 2. 把网页本来有的cookie接上
    NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL URLWithString:URL_HOME]];
    for (NSHTTPCookie *cookie in cookies) {
        [cookieString appendString:[NSString stringWithFormat:@"%@=%@;(这个分号同样不能忘)", cookie.name, cookie.value]];
    }
       
    // 3. 在request里面添加上cookie
    NSURL *url = [NSURL URLWithString:urlString];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setValue:cookieString forHTTPHeaderField:@"Cookie"];
    
    // 4. webView 发起request请求
    [_webView loadRequest:request];
    
    // 5. 在WKWebView的代理方法didCommitNavigation里面设置cookie
    - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
    //    [webView setAllCookie];
        [webView evaluateJavaScript:@"document.cookie = 'name=zhang';" completionHandler:nil];
    }
    

    后续的问题:这个方案执行过程中可能会遇到一些问题,当然方案本身没有问题,一定是你的问题。

    1. 后台只能收到部分cookie,有的cookie收不到
      有次,后台问我:那个啥啥cookie你没有设置吧!其他cookie都有,就这个收不到。我:不可能吧,我看我代码里把所有cookie都设了啊,我不管了。于是后台去排查了半天,发现,一串cookie字符串的末尾,少了个分号;。。。
      🤣没错,是我的问题,在步骤1里我的cookieString大概是这样的@"c1=v1;c2=v2;......;name=aaa",aaa后面的;呢??大概被我吃了吧。

    2. 后台没有收到任何cookie,也就是这个方法似乎无效
      这个问题有个读者也问过我,我也不知道什么情况,也没给他解决。
      而那天我似乎遇到了同样的情况,大概是这样的,在一个列表里选择item>item选择完毕,表示待会要设置新cookie> 回到webView的页面>webView刷新>结果,抓包显示后台没有收到cookie。
      仔细看看这个流程,webView加载数据的过程中只做了一个操作,刷新。那么就真相大白了,刷新操作并不经过重新拼接cookie,不经过生成新的request请求过程,因此也就根本没有发送cookie。
      正确的做法,凡是要设置新的cookie,从后台拿新数据,那么,不要刷新,重新拼接cookie字符串,重新loadRequest吧。

    相关文章

      网友评论

      • 440bd488f596:不行啊·哥们儿,服务器那边说拦截不到,报错
        广锅锅:@440bd488f596 我说的分号是cookieString里面要加的分号,这个一定不能遗漏的。还有就是发起的request请求要使用NSMutableURLRequest,这个类才能带上cookie属性。
        440bd488f596:@广锅锅 加了呢
        广锅锅:第一步里面的分号加了吗?

      本文标题:WKWebView 设置Cookie

      本文链接:https://www.haomeiwen.com/subject/tlxinttx.html