平常的app开发中只调用Rest Api可能用不到Cookie,但是当要在App中内嵌WebView就有可能要用到。最近用到了这一块的东西,总结一下。

Cookie原理

关于cookie的原理简单描述就是下图:

iOS浏览器查看cookie iphone浏览器cookie_移动开发

server通过Set-Cookie或者Set-Cookie2来告诉浏览器存储cookie,然后在后续请求(通过domain和path来判断是否应该包含在某个请求中)中传回服务器。cookie可以分为会话cookie和持久cookie。会话cookie在浏览器关掉之后就会清除,而持久cookie会被存储在磁盘上,通过有效期来管理其生命周期。详情可以参考:https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies

HTTPCookie对象(OC中的类名叫NSHTTPCookie)

HTTPCookie对象是iOS中用来描述cookie信息的。有如下属性:



var domain: String   Cookie所属的domain
var expiresDate: Date?  Cookie的过期时间
var isHTTPOnly: Bool 用来标示Cookie是否只允许通过Http请求携带,而不能通过javascript获取到。
var isSecure: Bool 用来标示cookie是否必须通过https请求传输
var isSessionOnly: Bool 用来标示cookie是否属于会话cookie
var name: String cookie的名字
var path: String cookie所应用的url path,指定之后只有指定url path的请求系统才会携带该cookie(/表示全部路径)
var value: String cookie的值
var version: Int cookie的版本(cookie目前一共有两个版本,因此此处的合法值为0或1)



HTTPCookie对象可以通过提供属性字典的方式创建,Foundation库提供了名为HTTPCookiePropertyKey的枚举来定义可以出现在属性字典中的key.

init?(properties: [HTTPCookiePropertyKey : Any])

HTTPCookieStorage对象        

在浏览器中访问网页时,浏览器负责管理cookie。而在App中我们通过UrlSession和UrlConnection发送网络请求时,底层的网络层也会自动的为我们管理cookie:从response中解析cookie缓存和从缓存自动取出对应cookie填充到UrlRequest对象中。 而HTTPCookieStorage对象则是负责存储cookie的地方。HTTPCookieStorage是系统提供的一个单例对象。它提供存取系统中cookie的接口。

当我们发送网络请求后,如果后台在Response中添加了cookie信息。当我们收到Response后,我们应该可以通过访问HttpCookieStorage.shared.cookies属性拿到后台添加的cookie信息。(在某些情况下不是这样的,后面会说明)

我们也可以通过HttpCookieStorage.shared.SetCookie接口来添加cookie对象到storage中。cookie被添加到HttpCookieStorage后当对应domain和path的请求被发送时(UrlSession或UIWebView请求都是可以的),该cookie就会被自动包含在UrlRequest中。

HttpCookieStorage对象还包含了清除cookie等接口,详情见https://developer.apple.com/documentation/foundation/httpcookiestorage

UrlSessionConfiguration中的Storage对象

上面说到的可以通过HttpCookieStorage.shared.cookies来访问后台添加的cookie信息在如下情况下会有问题:使用通过NSURLSessionConfiguration.ephemeralSessionConfiguration来构造的UrlSession来发送的请求。

原因是ephemeralSessionConfiguration默认时候的CookieStorage是私有的CookieStorage对象,而不是前面所说的HttpCookieStorage单例对象。因此通过这种UrlSession收到的cookie都被其私有的CookieStorage所存储,也就不能被共享了(通过改UrlSession对象发送的请求是共享的)。要实现这种UrlSession对象的cookie也能存储在HTTPCookieStorage单例对象的方法也很简单。只需要我们在创建UrlSession对象时修改UrlSessionConfiguration对象的HTTPCookieStorage属性即可。



 

var config = URLSessionConfiguration.ephemeralSessionConfiguration
config.HTTPCookieStorage = HTTPCookieStorage.shared
var session = UrlSession(configuration:config);



不跨进程              

iOS系统对cookie的跨进程共享做了限制。看官方文档:

Each cookie is represented by an instance of the HTTPCookie isSessionOnly true) are local to a single process and are not shared.

iOS Note

Cookies are not shared among applications in iOS.