学计算机的那个

不是我觉到、悟到,你给不了我,给了也拿不住;只有我觉到、悟到,才有可能做到,能做到的才是我的.

0%

HTTP协议无状态

http是无状态(HTTP/1.0)的协议,HTTP/1.0之后呢?

无状态

HTTP协议本身是不对请求和响应之间的通信状态保存的。那为什么要这样呢?其实这主要是为了更快地处理大量的请求,确保协议的可伸缩性,特意将协议设计的这么简单。

那如果要保存状态该怎么办?HTTP/1.1就提出了解决方案,虽然还是无状态的,但是引入了Cookie技术,相比大家上网的话都应该碰到过“询问退出是否清除Cookie”,就是这个东西。当有了cookie之后,就可以管理状态了。

访问国外的一些标准网站的话,可能经常会弹出一个对话框,说是本网站为了更好的体验和跟踪,需要访问你的cookies,问你同意不同意

原理

1
2
3
4
5
根据服务端发送来的响应报文中,有个set-Cookie的首部字段,通知客户端保存cookie。
等到下次客户端需要访问服务端的时候,将保存的cookie发送出去。

服务器端发现客户端发送过来的 Cookie 后,会去检查究竟是从哪一个客户端发来的连接请
求,然后对比服务器上的记录,最后得到之前的状态信息

第一次请求:

第二次请求:

上面的图不有趣看下面的

HTTP 请求报文和响应报文的内 容如下

  1. 请求报文(没有 Cookie 信息的状态)
1
2
GET /reader/ HTTP/1.1
Host: hackr.jp *首部字段内没有Cookie的相关信息
  1. 响应报文(服务器端生成 Cookie 信息)
1
2
3
4
5
6
HTTP/1.1 200 OK
Date: Thu, 12 Jul 2012 07:12:20 GMT
Server: Apache
<Set-Cookie: sid=1342077140226724; path=/; expires=Wed, 10-Oct-12
07:12:20 GMT>
Content-Type: text/plain; charset=UTF-8
  1. 请求报文(自动发送保存着的 Cookie 信息)
1
2
3
GET /image/ HTTP/1.1
Host: hackr.jp
Cookie: sid=1342077140226724

作用

Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,浏览器之后向同一服务器再次发起请求时会携带上该cookie,用于告知服务端两个请求是否来自同一浏览器

由于之后每次请求都会需要携带 Cookie 数据,因此会带来额外的性能开销(尤其是在移动环境下)。

Cookie 曾一度用于客户端数据的存储,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。

使用场景

  1. 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
  2. 个性化设置(如用户自定义设置、主题等)
  3. 浏览器行为跟踪(如跟踪分析用户行为等)

Cookie的创建过程

1.服务器将cookie通过响应报文中的 Set-Cookie 首部字段发送给客户,客户端得到响应报文后把 Cookie 内容保存到浏览器中

1
2
3
4
5
6
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry

[page content]

2.客户端之后对同一个服务器发送请求时,会从浏览器中取出 Cookie 信息并通过 Cookie 首部字段发送给服务器。

1
2
3
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry

Cookie的分类

会话期 Cookie: 浏览器关闭之后它会被自动删除,也就是说它仅在会话期内有效。
持久性 Cookie: 指定过期时间(Expires)或有效期(max-age)之后就成为了持久性的 Cookie。

1
Set-Cookie: id=abcdef; Expires=Thu, 31 May 2021 08:00:00 GMT;

其中Expires是HTTP1.0中定义的header,Max-Age是HTTP1.1中定义的header。

Cookie的权限控制

Secure 和 HttpOnly

HTTP提供了两个属性来对cookies的权限进行控制,分别是SecureHttpOnly

如果cookies中带有Secure属性,那么cookies只会在使用HTTPS协议的时候发送给服务器。如果使用的是HTTP协议,则不会发送cookies信息。

如果cookies设置了HttpOnly,那么cookies是不允许被JavaScript访问的,通过设置HttpOnly,我们可以提升客户端数据的安全性:

1
Set-Cookie: id=abcdef; Expires=Thu, 21 May 2021 08:00:00 GMT; Secure; HttpOnly

Domain和 Path

cookies还可以添加Domain和Path属性,用于标记cookies可以发送到的URL。

其中Domain表示域名,而Path表示路径。

如果Domain没有设置,则默认是设置cookies的host,这个host是不包含子domain的。如果手动指定了Domain,那么子domain是会包含在内的。

比如如果我们设置了Domain=flydean.com,那么子domain:doc.flydean.com也会共享这个cookies。

Path用来匹配URL的路径,只有匹配到的URL才可以发送cookies。

SameSite

SameSite属性,表示如果是在CORS环境情况下,是否发送cookies到第三方网站,这样可以在一定程度上保护网站的信息。

SameSite有三个可能的值,分别是Strict, Lax, 和 None

1
Set-Cookie: name=flydean; SameSite=Strict

Session

session 是一个抽象概念,开发者为了实现中断和继续等操作,将 user agentserver 之间一对一的交互,抽象为“会话”,进而衍生出“会话状态”,也就是 session 的概念

Cookie 是一个实际存在的东西,http 协议中定义在 header 中的字段。可以认为是 session 的一种后端无状态实现。

Session 因为 Session id 的存在,通常要借助 cookie 实现,但这并非必要,只能说是通用性较好的一种实现方案

  • session将用户信息存储在服务器端,这样信息会更加安全。
  • Session 可以存储在服务器上的文件、数据库或者内存中。也可以将 Session 存储在 Redis 这种内存型数据库中,效率会更高。

Session维护用户登录状态的过程

  1. 用户进行登录时,用户提交包含用户名和密码的表单,放入 HTTP 请求报文中。
  2. 服务器验证该用户名和密码,如果正确则把用户信息存储到 Redis 中,它在 Redis 中的 Key 称为 Session ID
  3. 服务器返回的响应报文的 Set-Cookie 首部字段包含了这个 Session ID,客户端收到响应报文之后将该 Cookie 值存入浏览器中。
  4. 客户端之后对同一个服务器进行请求时会包含该 Cookie 值,服务器收到之后提取出 Session ID,从 Redis 中取出用户信息,继续之前的业务操作。

使用session ID要注意的问题:

  1. 为了不让 Session ID 被恶意攻击者轻易获取,那么就不能产生一个容易被猜到的 Session ID 值。
  2. 需要经常重新生成 Session ID。
  3. 在对安全性要求极高的场景下,例如转账等操作,除了使用 Session 管理用户状态之外,还需要对用户进行重新验证,比如重新输入密码,或者使用短信验证码等方式。

大多数的应用都是用 Cookie 来实现Session跟踪的

Cookie 只能存储 ASCII 码字符串,而 Session 则可以存储任何类型的数据,因此在考虑数据复杂性时首选 Session。
Cookie 存储在浏览器中,容易被恶意查看。如果非要将一些隐私数据存在 Cookie 中,可以将 Cookie 值进行加密,然后在服务器进行解密。
对于大型网站,如果用户所有的信息都存储在 Session 中,那么开销是非常大的。因此,不建议将所有的用户信息都存储到 Session 中。

如果浏览器禁用cookie,怎么办?

此时无法使用 Cookie 来保存用户信息,只能使用 Session。
除此之外,不能再将 Session ID 存放到 Cookie 中,而是使用 URL 重写技术来进行会话跟踪,将 Session ID 作为 URL 的参数进行传递。

参考

1.计算机网之应用层
2.HTTP系列之:HTTP中的cookies
3.HTTP cookies
4.COOKIE和SESSION有什么区别?