3

HTTP协议当初为了让协议尽量简洁,制定为无状态协议,即指每次request请求之前是相互独立的,当前请求并不会记录它的上一次请求信息。那么问题来了,开发中经常需要用到状态记录,比如日常的登录网站,不可能每次登录都要客户重新输入密码,这样用户体验肯定会很差,那如何让无状态的http协议将状态记录下来呢?
于是浏览器厂商发明了cookie来解决这个难题。
Cookie总是保存在客户端中,按在客户端中的存储位置,可分为内存Cookie和硬盘Cookie,设置了过期时间Expires(Cookie的几个属性之一)的Cookie会存储在硬盘里面,不同操作系统cookie的储存路径会有所不同,而没有设置该属性的Cookie会存储在内存里面,此时浏览器的选项卡可以共享同一个cookie信息,关闭浏览器就会清除该Cookie!
首先看一下cookie在前后端交互中的应用:
cookie的应用

第一次验证成功后,服务端会在响应头信息中带上“set-cookie”字段,浏览器监测到该字段之后,会把其中的值对号入座写入浏览器的cookie的属性中

服务端返回set-cookie

存储在cookie中的数据,在它过期之前,每次都会被浏览器自动放在http请求中,如果这些数据并不是每个请求都需要发给服务端的数据,浏览器这设置自动处理无疑增加了网络开销;但如果这些数据是每个请求都需要发给服务端的数据(比如身份认证信息),浏览器这设置自动处理就大大免去了重复添加操作。所以对于那设置“每次请求都要携带的信息(最典型的就是身份认证信息token)”就特别适合放在cookie中。而服务器端通过验证cookie中的信息,实现了验证,也让浏览器端省去了每次都需要输入登录信息的麻烦。

图片描述

为了实现cookie的作用,除了name和value之外,设计者还给它增加了七个属性,分别是expires/max-age、domain、path、secure、HttpOnly、samesite,这些属性是通过cookie选项来设置的,在设置任一个cookie时都可以设置相关的这些属性,当然也可以不设置,这时会使用这些属性的默认值。

cookie的六个属性

Expires和Max-Age
expires选项用来设置“cookie 什么时间内有效”。expires其实是cookie失效日期,expires必须是 GMT 格式的时间(可以通过new Date().toGMTString()或者 new Date().toUTCString() 来获得)。
如expires=Thu, 25 Feb 2016 04:18:00 GMT表示cookie讲在2016年2月25日4:18分之后失效,对于失效的cookie浏览器会清空。如果没有设置该选项,则默认有效期为session,即会话cookie。这种cookie在浏览器关闭后就没有了,属于内存cookie。而max-age就是cookie写入之后的有效时长,比如max-age=600就是600秒后,cookie则会失效。max-age的优先级高于expires

domain 和 path
domain是域名,path是路径,两者加起来就构成了 URL,domain和path一起来限制 cookie 能被哪些 URL 访问,domain属性的默认值是创建cookie的网页所在服务器的主机名。不能将一个cookie的域设置成服务器所在的域之外的域,要想cookie在多个二级域名中共享,需要设置domain为顶级域名。

HttpOnly
告知浏览器不允许通过脚本document.cookie去更改这个值,同样这个值在document.cookie中也不可见。但在http请求张仍然会携带这个cookie。注意这个值虽然在脚本中不可获取,但仍然在浏览器安装目录中以文件形式存在。

secure
安全标志,指定后,只有在使用SSL链接(https)时候才能发送到服务器,如果是http链接则不会传递该信息。就算设置了secure 属性也并不代表他人不能看到你机器本地保存的 cookie 信息,所以不要把重要信息放在cookie中。

samesite
主要为了防御CSRF攻击(跨站点请求伪造)而添加的cookie属性,SameSite=Strict严格模式,表明这个 cookie 在任何情况下都不可能作为第三方 cookie,有兴趣了解可以查下“csrf攻击”的资料

除了服务器端返回的set-cookie字段,浏览器端也可以对cookie进行操作,有npm为我们封装好的插件js-cookie: https://www.npmjs.com/package...,不过我们还是用原生方法手动实现一遍

获取cookie:
在控制台输入document.cookie,或者js代码中console.log(document.cookie)可以得到下图:
图片描述
可以看到,cookie是一个个键值对(“键=值”的形式)加上分号空格隔开组合而成, 形如: "name1=value1; name2=value2; name3=value3",可以用正则表达式来提取等号后面的值

function getCookie(name) {
  var value = '; '+ document.cookie;
  var parts = value.split('; ' + name + '=');
  if(parts.length === 2) {
    return parts.pop().split(';').shift();
  }
}

写入cookie

function setCookie (name, value, day) {
  if(day !== 0){     //当设置的时间等于0时,不设置expires属性,cookie在浏览器关闭后删除
    var expires = day * 24 * 60 * 60 * 1000
    var date = new Date(+new Date()+expires);
    document.cookie = name + "=" + escape(value) + ";expires=" + date.toUTCString()
  }else{
    document.cookie = name + "=" + escape(value)
  }
}

注意:expires使用GMT或UTC格式的时间, 我这里没有指定路径(path)和域(domain), 当没有指定路径时默认为当前路径下,如对 于“https://home.cnblogs.com/u/ma...”下设置的cookie,其path为"/u/maderlzp", 其domain为当前域名“home.cnblogs.com”

删除cookie
设置cookie过期时间小于当前时间,那么就会删除该cookie

function deleteCookie(name) {
  document.cookie = name + '=;  expires=Thu, 01 Jan 1970 00:00:01 GMT;'
}

Cookie具有不可跨域名性。根据Cookie规范,浏览器访问Google.com只会携带Google.com的Cookie,而不会携带Baidu.com的Cookie。Google.com也只能操作Google.com的Cookie,而不能操作Baidu.com的Cookie

<完>


广州鹏少
87 声望4 粉丝