iOS开发Swift

Swift – Cookie内容的读取、删除、写入(附:手动清除Session)

一、基本概念介绍
1,Cookie 介绍

(1)Cookie 是在 HTTP 协议下,服务器或脚本可以维护客户工作站上信息的一种方式。Cookie 是由 Web 服务器保存在用户浏览器(客户端)上的小文本文件,它可以包含有关用户的信息。


(2)无论何时用户链接到服务器,浏览器都会把请求的网址连同该 Cookie 一同提交给服务器。服务器检查该 Cookie,以此来辨认用户状态。

(3)目前有些 Cookie 是临时的,有些则是持续的。

  • 临时的 Cookie 只在浏览器上保存一段规定的时间,一旦超过规定的时间,该 Cookie 就会被系统清除。
  • 持续的 Cookie 则保存在用户的 Cookie 文件中,下一次用户返回时,仍然可以对它进行调用。
2,Session 介绍

(1)Session 是另一种记录客户状态的机制,不同的是 Cookie 保存在客户端浏览器中,而 Session 保存在服务器上。

(2)客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是 Session

(3)实际上大多数的应用都是用 Cookie 来实现 Session 跟踪的。即第一次创建 Session 的时候,服务端会在 HTTP 协议中告诉客户端,需要在 Cookie 里面记录一个 Session ID,以后每次请求把这个会话 ID 发送到服务器,我就知道你是谁了。

(4)如果客户端的浏览器禁用了 Cookie,那么通常会使用一种叫做 URL 重写的技术来进行会话跟踪,即每次 HTTP 交互,URL 后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。

3,iOS 系统对 Cookie 的管理

(1)iOS 提供了一个门用来管理 Cookie 数据的类:HTTPCookieStorage,而其中每一个 Cookie 数据又对应一个 HTTPCookie 类对象。

(2)每一个 HTTPCookie 对象里面封装一个 Cookie 数据,方便我们读取 Cookie 内容。

(3)通常情况下我们可以不用管 Cookie,如果 Response 中带有 CookieiOS 会自动调用 HTTPCookieStorage,把 Cookie 数据保存下来。当有新的请求时,URLRequest 会自动带上相应的 Cookie 数据。

(4)这个机制不仅适用于 URLSession,同样适用于 SwiftHTTPAlamofire 等第三方 HTTP 网络操作库。

(5)注意:由于 iOS 安全策略,不同 APP 之间是无法共享 Cookie 的。

4,iOS 系统中 Cookie 保存在哪里?

从最前面 Cookie 的介绍部分可以得知,Cookie 是会被持久化到文件中。而 iOS 平台下的地址是则是沙盒的:/Library/Cookies/******.binarycookies

比如下图,我的应用访问了 hangge.com,并保存相关 Cookie

二、Cookie 的读取
1,服务端代码(cookie.php)
  • 访问这个 php 页面后会分别设置两个 cookie 值和两个 session 值。
  • 其中 session 虽然保存在服务器上,但在客户端这边仍然需要通过 cookie 保存个 Session ID。所以客户端实际一个共会存放 3 个cookie 值。
<?
//设置Cookie值(全站有效,1小时后失效)
setcookie("cookie1","111", time() + 3600, "/");
setcookie("cookie2", "222", time() + 3600, "/");
 
//设置Session值
session_start();
$_SESSION["session1"]=333;
$_SESSION["session2"]=444;
?>
2,样例代码(ViewController.swift)

程序启动后通过 URLSession 访问上面的那个 php 页面,系统会自动保存 Cookie。点击“读取Cookie”按钮,则将该域名下的所有 Cookie 值打印到控制台中。

import UIKit
 
class ViewController: UIViewController {
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        //创建URL对象
        let urlString = "http://www.hangge.com/cookie.php"
        let url = URL(string:urlString)
        //创建请求对象
        let request = URLRequest(url: url!)
         
        let session = URLSession.shared
        let dataTask = session.dataTask(with: request, completionHandler: {
            (data, response, error) -> Void in
            print("请求结束!")
        }) as URLSessionTask
         
        //使用resume方法启动任务
        dataTask.resume()
    }
     
    @IBAction func loadCookies(_ sender: Any) {
        let url = URL(string: "http://www.hangge.com")!
        let cstorage = HTTPCookieStorage.shared
        if let cookies = cstorage.cookies(for: url) {
            for cookie:HTTPCookie in cookies {
                print("name:\(cookie.name)", "value:\(cookie.value)")
            }
        }
    }
     
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
三、Cookie 的编辑
1,删除 Cookie

通过 HTTPCookieStorage 的 deleteCookie 我们可以删除指定的 Cookie,如果想要清空所有的 Cookie 可以通过如下方式实现:

let cstorage = HTTPCookieStorage.shared
if let cookies = cstorage.cookies(for: url) {
    for cookie in cookies {
        cstorage.deleteCookie(cookie)
    }
}

注意:对于 Session 来说,如果把存储 Session ID 的 Cookie 给删除了,服务器自然也找不到对应的 session

2,创建 Cookie

(1)在 iOS 中,每个 Cookie 数据都是一个 HTTPCookie 对象。客户端这边如果需要手动设置一个 Cookie,也就是创建一个 HTTPCookie 对象。

(2)创建完毕后,通过 HTTPCookieStorage 的 setCookie 方法,就可以把 Cookie 保存起来。

  • 如果原来存在同名的 Cookiename 相同),则覆盖。
  • 如果原来不存在该名字的的 Cookie,则新增。
//创建一个HTTPCookie对象
var props = Dictionary<HTTPCookiePropertyKey, Any>()
props[HTTPCookiePropertyKey.name] = "cookie3"
props[HTTPCookiePropertyKey.value] = "333"
props[HTTPCookiePropertyKey.path] = "/"
props[HTTPCookiePropertyKey.domain] = "www.hangge.com"
let cookie = HTTPCookie(properties: props)
 
//通过setCookie方法把Cookie保存起来
let cstorage = HTTPCookieStorage.shared
cstorage.setCookie(cookie!)

(3)后面当程序再发送请求时,如果 URl 正是创建 HTTPCookie 时指定的 HTTPCookieDomain 值时,就会自动发送这个 Cookie 了。

(4)如果没有设置 Cookie 失效时间,程序退出后这个 Cookie 是不会自动保存的。如果想要持久化 Cookie,给它设置个失效时间,这样下次启动 app 该 Cookie仍然存在。

//90天后过期
props[HTTPCookiePropertyKey.expires] = Date().addingTimeInterval(3600*24*90)