这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战
- 什么是
session,什么是cookiecookie的安全问题和解决措施
为什么叫被遗忘的Cookie呢? 因为目前SessionStorage和LocalStorage大道其行了。毕竟操作什么的比Cookie方便太多了,哈哈哈!
1. Cookie和Session
HTTP 协议是一种无状态协议,即每次服务端接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录; Cookie 和Session 的主要目的就是为了弥补 HTTP 的无状态特性。
说起Cookie,Session还是得提一嘴
1.1 Session是什么?
客户端请求服务端,服务端会为这次请求开辟一块内存空间,这个对象便是 Session 对象,存储结构为 ConcurrentHashMap。Session 弥补了HTTP无状态特性,服务器可以利用 Session 存储客户端在同一个会话期间的一些操作记录。
1.1.1 Session 如何判断是否是同一会话?
服务器第一次接收到请求时,开辟了一块 Session 空间(创建了Session对象),同时生成一个 sessionId ,并通过响应头的 Set-Cookie:JSESSIONID=123xxx 命令,向客户端发送要求设置 Cookie 的响应; 客户端收到响应后,在本机客户端设置了一个**JSESSIONID=123xxxx** 的 Cookie信息,该 Cookie 的过期时间为浏览器会话结束
接下来客户端每次向同一个网站发送请求时,请求头都会带上该 Cookie信息(包含 sessionId ), 然后,服务器通过读取请求头中的 Cookie 信息,获取名称为 JSESSIONID 的值,得到此次请求的 sessionId。
【Cookie和session的关联图:】
【补充】:
Set-Cookie是响应头首部字段,Cookie是请求头首部字段
【扩展】: 其实判断是否是同一会话,也可以用接口将这个值传回来,然后本地保存在SessionStorage也是一种方式,请求信息的时候把这个值从SessionStorage拿出来回传给服务器也是可以的。
1.1.2 Session 的缺点
Session 机制有个缺点,比如 A 服务器存储了 Session,就是做了负载均衡后,假如一段时间内 A 的访问量激增,会转发到 B 进行访问,但是 B 服务器并没有存储 A 的 Session,会导致 Session 的失效。
1.2 Cookie是什么?
其实Cookie是对http无状态的一种改良方式,是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上
Cookie 主要用于会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)。由于服务器指定Cookie 后,浏览器的每次请求都会携带 Cookie 数据,会带来额外的性能开销(尤其是在移动环境下),所以不要在Cookie上存储过多的数据信息
1.2.1 创建Cookie
也就是前面提到的服务器在响应头添加Set-Cookie:<cookie名>=<cookie值>,下面以node.js为例子
response.setHeader('Set-Cookie', ['type=cookiename', 'language=cookievalue']);
这样设置后响应头表现:
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: type=cookiename
Set-Cookie: language=cookievalue
[页面内容]
然后,对该服务器发起的每一次新请求,浏览器都会将之前保存的Cookie信息通过 Cookie 请求头部再发送给服务器。表现如下:
GET /index.html HTTP/1.1
Host: www.example.org
Cookie: type=cookiename; language=cookievalue
在js端设置Cookie推荐使用js-cookie这个库,使用文档:js-cookie,不过为了安全一般都是设置http-only防止js能修改Cookie
1.2.2 Cookie的分类
按Cookie 的生命周期可以分成2类:
- 会话期
Cookie,也就是没有设置过期时间,浏览器关闭就自动删除,没有存入硬盘 - 持久性
Cookie的生命周期取决于过期时间(Expires)或有效期(Max-Age)指定的一段时间。是存入硬盘了的
2. 关于Cookie的安全问题
2.1 Cookie的作用域(同源策略)
其实这个东西是由Cookie的两个重要属性所决定的,即Domain和Path,也就是允许 Cookie 应该发送给哪些URL
-
Domain,指定 cookie 可以送达的主机名。假如没有指定,那么默认值为当前文档访问地址中的主机部分(但是不包含子域名)。与之前的规范不同的是,域名之前的点号会被忽略。假如指定了域名,那么相当于各个子域名也包含在内了 -
Path,指定一个 URL 路径,这个路径必须出现在要请求的资源的路径中才可以发送Cookie首部,此目录的下级目录也满足匹配的条件
如何跨域携带Cookie信息呢?
通过设置 withCredentials: true ,发送Ajax时,Request header中便会带上 Cookie信息。
对应客户端的 xhrFields.withCredentials: true 参数,服务器端通过在响应 header 中设置 Access-Control-Allow-Credentials = true 来运行客户端携带证书式访问。通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie。
这里需要注意的是: 服务器端 Access-Control-Allow-Credentials = true时,参数Access-Control-Allow-Origin 的值不能为 '*'
2.2 使用Secure属性
标记为 Secure 的 Cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端,因此可以预防 man-in-the-middle(中间人攻击) 攻击者的攻击,即便是设置了这个,也不应该在Cookie存储敏感信息,因为该信息可以很容易通过其他方式获取
Set-Cookie: Secure
2.3 使用HttpOnly属性防止通过JavaScript 访问 cookie 值。
2.4 使用Cookie存储敏感信息的措施
用于敏感信息(例如指示身份验证)的 Cookie 的生存期应较短,并且 SameSite 属性设置为Strict 或 Lax。在支持 SameSite 的浏览器中,这样做的作用是确保不与跨域请求一起发送身份验证cookie,可以在一定程度上防止CSRF攻击
参考资料
- 看完这篇 Session、Cookie、Token,和面试官扯皮就没问题了
- JavaScript高级程序语言设计
- mozilla.org