39- WKWebView项目实践分享(四) - 先了解下Cookie

0.095字数 1103阅读 292

在解决WKWebView中的Cookie问题之前,我们先来简单了解一下Cookie是什么。

如果你之前没有接触过Cookie,那么只需要记住Cookie是我们日常浏览的网页页面为了识别具体的用户身份,而在request Header加带的一种数据。有了这个数据,你要浏览的的网页就知道你是哪个用户。
举个例子:如果浏览网站的时候没有Cookie或者Cookie失效了,那么就会出现这种情况。你隔了好多天访问微博网页,点击的标签明明之前保存的是你登录之后的微博首页,可以直接看到你的好友动态。但是现在它却给你跳转了登录页面先要你登录。就是因为你Cookie失效导致的。微博没办法判断你是否是有效用户了。

另外,我们需要特别注意,在页面跳转的时候,网站有时候会自己在request Header中加入一些Cookie,也作为身份校验的一部分。


request Http Header

如何设置和获取Cookie

首先Cookie可以由native端设置也可以由服务端来设置。

native端设置了Cookie之后,保存在request Header当中。网站自己想要获取这个Cookie,其中一种方式是通过JS的原生API方法document.cookie获取。

需要注意的是,native端也可以通过操作document.cookie的方式,达到管理(增删改查)网页中document.cookie的目的。 这一点很重要,因为在之后的WKWebView关于Cookie的解决方案中会用的。

还有,服务器在request过程中也会设置一些Cookie,服务器设置Cookie是在服务器开始响应的时候,通过response header的一个set-cookie,专门用来设置cookie。

那么,如果客户端想要打印出webView中的Cookie,就有四个地方可选了:

  1. native端设置Cookie的时候
  2. 获取request Header
  3. 获取document.cookie的内容
  4. 获取response header中的set-cookie

下边来说一下如何在这四个地方获取
第一个,我们需要知道iOS这边管理Cookie会用到两个类NSHttpCookieStorageWKHttpCookieStore。具体关于这两个使用,后面文章会提到,这里只看看获取的方法:

+ (void)logCookiesFromHTTPCookieStore
{
    if (@available(iOS 11.0, *)) {
        WKWebsiteDataStore *store = [WKWebsiteDataStore defaultDataStore];
        [store.httpCookieStore getAllCookies:^(NSArray<NSHTTPCookie *> * cookies) {
            [cookies enumerateObjectsUsingBlock:^(NSHTTPCookie * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                NSLog(@"-->count:%zd; name:%@; value:%@",cookies.count, obj.name, obj.value);
                
            }];
        }];
    }
    else {
        NSArray *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies;
        for (NSHTTPCookie *cookie in cookieJar) {
            NSLog(@"-->count:%zd; name:%@; value:%@",cookieJar.count, cookie.name, cookie.value);
        }
    }
}

第二个,直接在WKUINavigationDelegate中的decidePolicyForNavigationAction打印就来可以。
第三个,方式比较多,可以使用User Script和Script Message的方式,可以翻看上一篇文章《38- WKWebView项目实践分享(三) native和WebView交互》

第四个,需要在在WKUINavigationDelegate中的decidePolicyForNavigationResponse打印相关数据。

+ (void)logCookiesFromNavigationResponse:(NSHTTPURLResponse *)response
{
    // FIXME:获取Cookie!!!
    NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];
    // 读取wkwebview中的cookie 方法1
    for (NSHTTPCookie *cookie in cookies) {
        //[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
        NSLog(@"-->wkwebview中的cookie:%@", cookie);
    }
    
    // -------------------- 分割线
    // 读取wkwebview中的cookie 方法2 读取Set-Cookie字段
    NSString *cookieString = [[response allHeaderFields] valueForKey:@"Set-Cookie"];
    NSLog(@"wkwebview中的cookie:%@", cookieString);
    // 看看存入到了NSHTTPCookieStorage了没有
    NSHTTPCookieStorage *cookieJar2 = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    for (NSHTTPCookie *cookie in cookieJar2.cookies) {
        NSLog(@"NSHTTPCookieStorage中的cookie%@", cookie);
    }
}

Cookie的属性和创建

Cookie的参数主要有Domain、Path、Name、Value、Expires,另外还有两个需要注意的参数Secure、HttpOnly

其中部分参数的含义:

  • Domain:表示域名,比如www.baidu.com
  • Path: 表示路径,比如 "/"、"/shop/book"
  • Name: 表示Cookie的名字
  • Value:表示Cookie要带的信息
  • Expires:表示Cookie的失效日期
  • Secure: 如果设置为ture,表明这个Cookie只在Https或者其它安全请求协议下,才被发送到服务器。默认不设置此项。
  • HttpOnly:如果设置为ture,表明不能通过JS代码去管理被设置的这个Cookie。默认不设置此项。

接下来,你可以在请求任意网站的时候,给这个网站的request Header中加上自定义的Cookie。只要这个Cookie和这个网站官方使用的Cookie名字不要冲突就好。需要注意,Domain、Path、Name、Value这四个属性是必须都有,Cookie才能有效。上代码:

{
    WKWebView *webView = [[WKWebView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    NSURL *url = [NSURL URLWithString:@"http://www.lilongcnc.cc"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [self addCookie];
    [webView loadRequest:request];
    [self.view addSubview:webView];
    
}

- (void)addCookie
{
    NSDictionary *mCookProperties = @{
                                      NSHTTPCookieDomain: @".lilongcnc.cc",
                                      NSHTTPCookiePath: @"/",
                                      NSHTTPCookieName: @"laurenKey",
                                      NSHTTPCookieValue:  @"laurenValue",
                                      };
    
    NSHTTPCookie *myCookie = [NSHTTPCookie cookieWithProperties:mCookProperties];
    [self saveCookie:myCookie];
}

// 添加Cookie到WebView的Cookie管理器
- (void)saveCookie:(NSHTTPCookie *)cookie
{
    if (@available(iOS 11.0, *)) {
        WKWebsiteDataStore *store = [WKWebsiteDataStore defaultDataStore];
        [store.httpCookieStore setCookie:cookie completionHandler:^{
        }];
        
        
    } else {
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
}

这里有个需要注意的地方,Path的路径/前边不要加"."。web资源路径和PC路径还是有区别的。 你见过 $ cd ./Home/User,但是你肯定没见过http://www.baidu.com./home.html

参考

交流


希望能和大家交流技术
Blog:http://www.lilongcnc.cc


推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
  • 目录Cookie机制什么是CookieCookie的不可跨域名性Unicode编码:保存中文BASE64编码:保存...
  • cookie机制 在程序中,会话跟踪是很重要的事情。理论上,一个用户的所有请求操作都应该属于同一个会话,而另一个用...
  • 会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Se...
  • 记得跟Nodejs + Cookie 这篇整合一下。https://segmentfault.com/a/1190...