zzzmj/duola-blog

详解cookie和session

Opened this issue · 0 comments

zzzmj commented

1. cookie

首先我们要明白,cookie是用来做什么的?

Cookie 是客户端保存用户信息的一种方式。(除此之外还有localStorage,sessionStorage)

由于HTTP协议是无连接,无状态的。
它就像给服务器写信一样,每个请求都是一封单独的信,服务端想要识别这每封信,
也就需要信上写上自己的地址。 因此引进了Cookie概念,客户端带上自己的Cookie去请求服务器

Cookie可以记录客户端一些信息,在每次发送HTTP请求的时候带上Cookie字段告诉服务器

服务器可以通过客户端的Cookie来识别用户,比如说就可以让用户直接登录,之类的

Cookie的工作流程

  1. 首先当前域名下没有Cookie
  2. 浏览器发送请求给服务器(这个请求告诉了服务器,我想保存用户信息,一般常见场景是在登录时候勾选免登录的复选框)
  3. 服务器知道了客服端想要保存Cookie,于是设置Cookie响应给客户端Set-Cookie: ...
  4. 浏览器接收到response响应,知道了这个Cookie信息
  5. 以后每次请求,浏览器都会带上这个Cookie发送给服务器

存在的安全隐患

既然Cookie是客户端保存的,那么就存在安全隐患

我们可以伪造HTTP请求,伪造Cookie字段,发送给服务器

....
Cookie: user=zmj

服务器误以为我们是用户zmj,返回了用户的相关信息

那么应该怎么解决这个安全隐患呢?就引入了Session的概念

2. Session

首先,我们思考,可以在Cookie工作流程的第三步中做手脚
想到一个方案,在服务器响应客户端,设置Cookie的时候,我们加密这个用户,让这个客户端就看不懂了

Set-Cookie: user=213d21shxfk97dmcxuids

那谁服务端怎么看懂它呢?

服务端把这个加密过后的东西叫做session_id,存在数据结构中,与User做一个映射

# 生成一个随机id
session_id = random_str()
# 与用户做映射
session[session_id] = username
# 设置Cookie
headers['Set-Cookie'] = 'user=' +session_id 

下次客户端发请求就会携带上这个一段乱码样的字符串

request
...
Cookie: user=213d21shxfk97dmcxuids

那么我服务端就可以通过session[cookie]获取到这段乱码对应的是哪个用户

3. session持久化

session持久化就是重启服务器后仍然可以使用
一般有两种实现方式

  • 保存到文件中,每次重启都读取这个文件
  • 对称加密

4. 进一步的思考

通过Session就能正确保证用户的安全了吗?

不是的,虽然我作为一个坏人看不懂Cookie是啥

但我可以如果截取到了你的HTTP请求,我知道你给服务器发送的Cookie是这个字段,那我照样可以伪造成你去做坏事

那这个怎么解决呢?就要通过HTTPS了,通过HTTPS我们加密HTTP请求。

HTTPS协议,简单来说,客户端有一个公钥,服务端有一个私钥。