需求场景一个Vue单页应用,A、B、C页面都引用了一个通用的时间选择器。用户在各自页面选择时间后,A、B、C页面相互切换时保存选择的时间。关闭浏览器选项卡后,所选时间被清除并恢复初始值。最初的想法是使用sessioncookies(不用手动设置过期时间),但是sessioncookies不会在浏览器标签页关闭时被清除。所以我决定研究一下sessioncookie什么时候被清除。Cookie后台HTTP是无状态协议,它不保存请求和响应之间的通信状态,即不能按照之前的状态处理本次请求。如果需要登录验证的网页本身无法管理状态,那么每次跳转到新的页面都需要重新登录,或者需要在请求消息中添加参数来管理登录状态。无状态协议有其优点,由于不需要保存状态,可以减少服务器的CPU和内存资源。为了在解决类似的矛盾问题的同时,保留无状态协议的特性,引入了cookies。原理cookie技术通过在请求和响应消息中写入cookie信息来控制客户端的状态。Cookie会根据服务器端响应报文中的一个名为Set-Cookie的头域信息通知客户端保存。当客户端下次向服务器发送请求时,客户端会自动在请求报文中添加cookie值并发送出去。服务器找到客户端发送的cookie后,会查看是哪个客户端发送的连接请求,然后比对服务器上的记录,最后得到之前的状态信息。客户端设置//属性用分号和空格分隔document.cookie='name=value;过期=日期;path=path'//设置多个cookiedocument.cookie='name=irene;domain=www.baidu.com';document.cookie='age=18;path=/welcome';document.cookie一次只能设置一个cookie,如果需要设置多个cookie,需要设置多次。客户端可以设置的属性有:expires、max-age、domain、path、secure(只有在https协议下才能设置成功),不能设置HttpOnly。服务器端设置Set-Cookie:name=value[;过期=日期][;域=域][;路径=路径][;secure]//设置多个cookieSet-Cookie:name=irene;域名=www.百度网;设置Cookie:年龄=18;路径=/欢迎;一个Set-Cookie只能设置一个cookie,如果需要设置多个cookie,需要多次使用Set-Cookie。除了设置cookie的名称和值外,还可以设置其他属性。服务器端可以设置的属性有:expires、max-age、domain、path、secure、HttpOnly等属性expires和max-age设置cookie的过期时间。expires的值是一个时间点(cookie过期时间=expires),max-age的值是秒数(cookie过期时间=创建时间+max-age)。expires是http/1.0协议中的一个选项,在新的http/1.1协议中expires已经被max-age选项取代。如果两者都存在,则max-age优先于expires。max-age有两个可能的值:小于等于0:有效期为最早可以表示的时间;大于0:有效期为当前时间+max-age。//expiresdocument.cookie='name=irene;expires=Wed,13Jun201910:28:27GMT'//max-age>0document.cookie='name=irene;max-age=3600'//max-age<=0document.cookie='name=irene;max-age=0'注意:一旦cookie从服务器发送到客户端,就没有办法在服务器上显式删除cookie。但是,可以通过覆盖cookie来删除客户端cookie。domain&pathDomain设置域名,默认为当前域名。path设置路径,默认为当前目录。域和路径一起限制哪些请求可以携带cookie。比如上面的第二个cookie,如果请求的URL的域名是juejin.com或者xxx.juejin.com,URL的路径是/或者子路径'/home',浏览器就会把这个cookie添加到cookie标头中的请求。//在https://juejin.im/welcome/frontend设置如下cookie,然后在浏览器cookie面板中显示domain=juejin.im,https中path=/welcomedocument.cookie='name=irene'////juejin.im/welcome/frontendjuejin.im/welcome/frontend设置如下cookie,浏览器cookie面板显示domain=.juejin.im(带前缀.),document.cookie='name=irene;域名=juejin.im;path=/welcome/frontend'//域前缀点与否请参考http://www.it1352.com/548425.htmlHttpOnly当设置了HttpOnly时,浏览器不会在非的header中添加cookieHTTP请求。设置cookie是否可以通过js访问(读取、修改、删除等)。默认情况下cookie没有HttpOnly选项,所以客户端可以通过js代码访问cookie。当cookie有HttpOnly选项时,客户端无法通过js代码访问cookie。主要目的是防止跨站脚本攻击窃取cookie信息。HttpOnly只能从服务器设置,不能从客户端设置。安全设置只能在HTTPS安全连接时发送cookie。浏览器是否携带cookie项的策略域匹配一个字符串(str)匹配(domain-matches)一个给定的域名字符串(domainstr)需要至少满足以下条件之一:str和domainstr恰好是相同(转换为小写并比较)。或同时满足以下条件:2.1域str为str的后缀。2.2str中最后一个不包含在域str中的字符是点(.)。域str=google.com;str=map.googole.com=>符合域str=google.com;str=map.mgoogle.com=>domainstr最后一个不包含的字符是m,不符合2.3str必须是域名,不是IP地址。path-matching一个请求路径(request-path)匹配(path-matches)给定的cookie-path需要至少满足以下条件之一:request-path和cookie-path完全相同。cookie-path是request-path的前缀,cookie-path的最后一个字符是/。cookie-path是request-path的前缀,request-path中第一个没有包含在cookie-path中的字符是/。注意:域匹配&路径匹配只是浏览器决定是否携带cookies的众多参考项中的两个,浏览器也会参考是否过期等项。实战题:如果cookie没有设置过期时间,默认是session结束过期。会话结束意味着浏览器的所有窗口都关闭了,或者是否足以关闭本网站的所有页面?具体场景:Chrome浏览器打开两次两个窗口A和B,A打开网站1的两个标签页(tab1&tab2)和网站2的两个标签页(tab3&tab4),B打开两个标签页(tab1&tab2)网站1和网站2的两个标签页(tab3&tab4),如果要让网站1的cookie失效,是直接关闭网站1的窗口AB的标签页还是需要关闭所有的浏览器的窗口?主题:https://segmentfault.com。它的PHPSESSION在session结束时无效,所以用来测试。工具:通过chrome://settings/cookies/detail?site=segmentfault.com查看本网站下的所有cookies。结论:所有浏览器窗口关闭,网站1的cookie(sessioncookie)失效。当浏览器窗口关闭时,Windows将退出程序,因此cookie将失效;mac在浏览器窗口关闭时不会退出程序,所以cookie不会失效,只有退出程序后cookie才会失效。规范如果cookie同时设置了Max-Age和Expires属性,则Max-Age优先。如果两者都没有设置,UA将保留cookie直到当前会话结束。
