在开始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,就有四个地方可选了:
- native端设置Cookie的时候
- 获取request Header
- 获取
document.cookie
的内容 - 获取response header中的
set-cookie
第一个,我们需要知道iOS这边管理Cookie会用到两个类NSHttpCookieStorage和WKHttpCookieStore。具体关于这两个使用,后面文章会提到,这里只看看获取的方法:
+ (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
。
参考
- 《聊一聊 cookie》
- 《理解Cookie和Session机制》
- Document.cookie
- HTTP cookies
- Set-Cookie
- 《Cookie 在前端中的实践》
- 《HTTP cookies 详解》
交流
希望能和大家交流技术
Blog:http://www.lilongcnc.cc
网友评论