0. 从http协议的无状态性说起
- http 是无状态的协议
- 无连接:处理完一个请求就断开链接(http1.1以后可以实现长连接)
- 无状态:上一次会话与下一次会话没有联系。
- 可以通过 cookie 来维护状态信息。
1. cookie
存储大小:每条的存储空间为4k;
特点:
- cookie没有显示的删除函数,可以设置 expire/max-age 过期时间,自动触发浏览器的删除机制。
- 服务器通过设置响应头来设置客户端的cookie,Set-Cookie: cookie-名=cookie值。可以同时添加多个Set-Cookie,从而设置多个cookie的值。
- 不允许存储敏感信息(用户名,密码等),一定要存储,要设置 cookie为 httponly, 另外考虑使用 非对称加密
- 浏览器 中的cookie 数量达到上限后,会删除旧的创建新的,删哪个由浏览器的策略决定
- cookie 通常与 session 一起使用。
- 登录时,server 端存储 用户信息相关的 session。
- server 端,生成的 sessionid 会放在cookie中,对应域名下就有了这个cookie。
- 以后会自动带这个 cookie,server 根据id 找到 session,获取用户信息。
基本操作
- 客户端:
// 读取:
document.cookie
// 设置:
document.cookie = 'myNmae=liulanqi;path=/;domain=.baidu.com';
-
服务端:
- 使用 setCookie 来设置,在设置多个 cookie的时候,得多写几个 setCookie。
设置cookie:
document.cookie="userId=828";
document.cookie="userName=hulk";
此时浏览器将会维护两个cookie,分别为userId和userName;相当于:
document.addCookie("userId=828");
document.addCookie("userName=hulk");
如果要改变一个cookie的值,只需重新赋值,例如:
document.cookie="userId=929";
获取cookie:
var strCookie=document.cookie;
console.log(strCookie); //userId=828; userName=hulk
- 只能一次获取所有的cookie的值,而不能指定cookie名称来获得指定的值。
- 如果在某个页面创建了一个cookie,那么该页面所在目录中的其他页面也可以访问该cookie。
- 为了控制cookie可以访问的目录,需要使用path参数设置cookie。document.cookie="userId=320; path=/shop";就表示当前cookie仅能在shop目录下使用。
-
常用的cookie操作及其函数实现:
- addCookie(name, value, expireHours):
function addCookie(name,value,expireHours){ var exdate = new Date(); exdate.setTime(exdate.getTime() + expireHours * 60 * 60 * 1000); document.cookie = name + "=" + escape(value) + ((expireHours == null) ? "" : ";expires=" + exdate.toUTCString()); } toUTCString() 方法可根据世界时 (UTC) 把 Date 对象转换为字符串,并返回结果。
- getCookie(name):
function getCookie(name){ let arr, reg = new RegExp(`^| ${name} = [^;]*;|$`); if (arr = document.cookie.match(reg)) return arr[2]; else return null; }
-
cookie的可选项:
-
expires/max-age: 设置过期时间。
- expires是绝对时间,max-age是相对时间。
- 如果没有设置过期时间,则表示是一个会话期cookie,在关闭浏览器后,会被移除。
- 浏览器支持会话恢复,保留cookie。
- 正数,表示 多少秒后失效
- 负数,该 cookie 是临时 cookie,关闭浏览器就失效,浏览器页不会以任何形式保存该 cookie
- 为 0,表示删除 cookie
-
domain和path:
- path,设置必须匹配的路径或者子路由才会发送cookie。如果路径设为/forums/,那么这个 Cookie 只有在访问www.example.com/forums及其子路径时才有效。
- path 的设置,必须以 ‘/’结尾
- domain 的设置,第一个字符必须是 ‘.’, 比如“.baidu.com”
- domain标识指定了哪些主机可以接受cookie。如果没有设置,则是当前主机(不包含子域名),否则为设置的域名(包含子域名)。
-
secure和httponly:
- secure标志cookie只能通过https传输,可以防止xss攻击。
- httponly表示cookie无法通过javascript调用,防止中间人劫持。把cookie设置为secure,只保证 cookie 与服务器之间的数据传输过程加密,而保存在本地的 cookie文件并不加密。如果想让本地cookie也加密,得自己加密数据。
- samesite:可以设置 SameSite:SameSite=Strict SameSite=Lax。则 cookie 不跨域发送。ajax中设置xhr.withCredentials = true;
-
:
问题:
- 问题:“www.qq.com” 与 “sports.qq.com” 公用一个关联的域名”qq.com”,我们如果想让”sports.qq.com” 下的cookie被 “www.qq.com” 访问:
- 解答:我们就需要用到cookie 的domain属性,并且需要把path属性设置为 “/“。例:document.cookie = “username=Darren;path=/;domain=qq.com“
- 问题:同域名的资源请求时,会默认带上本地的cookie,如何优化?
- 解答:将静态资源分组,分别放在不同的子域下(子域名请求时,是不会带上父级域名的cookie的)
cookie 的跨域问题
- 域名、端口相同就不算跨域,协议可以不同。
使用cookie需要考虑的问题
- 因为存储在客户端,容易被客户端篡改,使用前需要验证合法性
- 不要存储敏感数据,比如用户密码,账户余额
- 使用 httpOnly 在一定程度上提高安全性
- 尽量减少 cookie 的体积,能存储的数据量不能超过 4kb
- 设置正确的 domain 和 path,减少数据传输
- cookie 无法跨域
- 一个浏览器针对一个网站最多存 20 个Cookie,浏览器一般只允许存放 300 个Cookie
- 移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。