啰嗦的话不说,直接上干货,概念性的东西,什么产生背景啥的自己组织一下语言就好了
session
session是用来在客户端与服务器之间保持状态的一种解决方案(由于http的无状态),主要特点:
数据保存在服务端,session存在过期时间
多数情况下session实现依赖cookie,通过cookie存放sessionId,也可通过URL编码的方式携带sessionId
session存放的数据的key不能为null(至少在java web中如此)
session存放的数据的value为null时视为删除操作(至少在java web中如此)
放源码,来自apache tomcat的session实现类
org.apache.catalina.session.StandardSession
cookie
cookie大小限制,最多4K。
cookie主要5大属性:
- name:名称
- value:值
- domain:作用域,默认情况下,cookie的domain是设置该cookie的web服务器的域名,如domain域为
.ccc.com
的cookie可以被www.aaa.ccc.com
和www.bbb.ccc.com
的网站所读取,不能将一个cookie的域设置成服务器所在的域之外的域 ;cookie的domain属性不与端口相关,即同IP不同端口的web服务有机会获取到对方的cookie(path值匹配的话) - path:路径值;服务器后端获取cookie的规则:设当前URI为:/a/b,cookie路径为path,服务器后端能获取到的cookie满足:
path.startsWith(URI) || URI.startsWith(path)
- expires/max-age:过期时间/最大“年龄”;根据过期时间 max-age 有3种情况:
- max-age > 0;cookie到期销毁,此时cookie存于磁盘
- max-age = 0;cookie已经过期,此时cookie销毁
- max-age < 0;cookie在关闭浏览器后销毁,此时cookie存于内存
另外还有两个属性值得关注:
secure:取值范围 true | false,是否仅支持https传输
SameSite:Chrome 51 开始,浏览器的 Cookie 新增加了一个SameSite属性,限制第三方 Cookie,用来防止 CSRF 攻击和用户追踪,该属性不在服务端体现(至少目前java web是这样)。取值范围:
Strict:完全禁止第三方 Cookie,任何跨域请求浏览器都不会发送cookie
Lax:次于Strict的限制级别,任何跨域大多数情况浏览器不会发送cookie,如下表
请求类型 示例 Lax 链接 <a href=”…”></a> 发送 Cookie 预加载 <link rel=”prerender” href=”…”/> 发送 Cookie GET 表单 <form method=”GET” action=”…”> 发送 Cookie POST 表单 <form method=”POST” action=”…”> 不发送 iframe <iframe src=”…”></iframe> 不发送 ajax $.get(“…”) 不发送 Image <img src=”…”> 不发送 None:不禁止第三方 Cookie,跨域请求浏览器都会发送cookie,当secure为true时,该值才有效(此条知识点以Chrome浏览器80版本之后为前提)
后端读写cookie
后端读取cookie的特点:
- 后端通过request对象获取cookie:
Cookie[] cookies = request.getCookies()
,值得注意的是获取到的cookie数量为0时,该方法返回的是null而不是空数组。
设当前访问的地址URI为 /xxx/yyy
,写入规则如下:
属性 | 后端写cookie的值 | 描述 | 浏览器实际存储的值 | 含义 |
---|---|---|---|---|
name | “abc” | “abc” | ||
name | null | null引用 | 后端抛IllegalArgumentException异常 | |
name | “”或” “ | 空白字符串 | 后端抛IllegalArgumentException异常 | |
name | “ abc”或“abc ” | 空白字符开头或结尾的字符串 | 后端抛IllegalArgumentException异常 | |
value | null | null引用 | “” | |
value | “” | 长度为0的字符串 | “” | |
value | “ “ | 空白字符串 | 后端抛IllegalArgumentException异常 | |
path | /xxx | 当前路径的或子路径 | /xxx | |
path | / | / 代表根 | ${contextPath} | web容器上下文 |
path | null | null引用 | ${contextPath} | web容器上下文 |
path | “”或” “ | 长度为0或空白字符串 | ${contextPath} | web容器上下文 |
path | xyz | 不以斜杠开头的字符串 | ${contextPath} | web容器上下文 |
path | /zzz | 其它路径 | /zzz | |
expires/max-age | age > 0 | 过期时间大于0秒 | age * 1000ms | cookie到期销毁 |
expires/max-age | age = 0 | 过期时间等于0秒 | 0ms | cookie已经过期,销毁 |
expires/max-age | age < 0 | 过期时间小于0秒 | N/A(Session) | 关闭浏览器时cookie销毁 |
- 当${contextPath}web容器上下文为空时,则写入浏览器的path为 /。
前端读写cookie
代码可封装如下
1 | function setCookie(name,value,age,path) { |
当前浏览器地址为 /xxx/yyy
属性 | 前端写cookie的值 | 浏览器实际存储的值 | 后端接受到的值 | 含义 |
---|---|---|---|---|
name | “abc” | “abc” | “abc” | |
name | “”或” “ | “” | ${value} | name无效,后端取出的name反而为其value值 |
name | “ abc” | “abc” | “abc” | 前端存cookie会处理name的首尾空白字符 |
name | null | “null” | “null” | null类型转换为”null”字符串 |
name | undefined | “undefined” | “undefined” | undefined类型转换为”undefined”字符串 |
value | “abc” | “abc” | “abc” | |
value | “” | “” | “” | |
value | “ “ | “” | “” | 前端存cookie会处理value的首尾空白字符 |
value | null | “null” | “null” | null类型转换为”null”字符串 |
value | undefined | “undefined” | “undefined” | undefined类型转换为”undefined”字符串 |
path | /xxx | /xxx | null(后端不感知path值) | |
path | /zzz | /zzz | null(后端不感知path值) | 其它路径 |
path | / | / | null(后端不感知path值) | / 根 |
path | xyz | /xxx | null(后端不感知path值) | 当前路径的前一级路径,若不存在则为 / |
path | undefined | /xxx | null(后端不感知path值) | 当前路径的前一级路径,若不存在则为 / |
path | null | /xxx | null(后端不感知path值) | 当前路径的前一级路径,若不存在则为 / |
path | “” | /xxx | null(后端不感知path值) | 当前路径的前一级路径,若不存在则为 / |
path | “ “ | /xxx | null(后端不感知path值) | 当前路径的前一级路径,若不存在则为 / |
expires | “Session” | N/A(Session) | -1(后端不感知过期时间) | 关闭浏览器时cookie销毁(存于内存) |
expires | t > 0 | 过期时间大于0秒 | -1(后端不感知过期时间) | cookie到期销毁(存于磁盘) |
expires | t < 0 | 过期时间小于0秒 | -1(后端不感知过期时间) | cookie已经过期,销毁 |
- 前端js代码写cookie时,过对
document.cookie
赋值进行设置cookie - 设置的属性基本都有默认值,如果设置的值是“无理”的,属性都会取默认值,path属性默认为当前路径的前一级路径,expires属性默认为”Session”。
- 设置的name和value属性会进行一定优化,需要主要后端取到实际值的不同
localStorage
localStorage属性在HTML5时增加,允许在浏览器中存储 key/value 对的数据,特点:
- 只支持string类型的存储,key和value哪怕set时是number类型也会转成string类型
- 遵循同源策略
- 永久存在浏览器中,除非手动删除
- 一般浏览器支持的是5M大小,不同的浏览器中会有所不同
- 浏览器发送请求时不会带上
sessionStorage
sessionStorage属性在HTML5时增加,允许在浏览器中存储 key/value 对的数据,特点:
- 只支持string类型的存储,key和value哪怕set时是number类型也会转成string类型
- 数据仅在当前浏览器窗口有效
- 一般浏览器支持的是5M大小,不同的浏览器中会有所不同
- 浏览器发送请求时不会带上
小结
数据存放位置 | 非手动情况下数据销毁时机 | |
---|---|---|
session | 服务端(依赖cookie存放sessionId) | session过期 |
cookie | 浏览器 | 到达过期时间 |
localStorage | 浏览器 | 必须手动删除 |
sessionStorage | 浏览器 | 浏览器窗口关闭 |