cookie
session
redis
一. 前言
最近在学习node的过程中对于cookie,session,redis有了和之前不一样的理解,记录一下之前不了解的知识点。
二.cookie的重点概念
- 存储在客户端浏览器中的字符串,最大5kb
- 跨域不共享,每一个域下的cookie都是不同的
- 由于字符串是非结构化的数据,为了存储结构化数据约定以 k1=v1;k2=v2;k3=v3格式来存储
- 每次发送一个http请求的时候(无论是请求网页,请求js,请求图片)都会携带请求域的cookie发送给server端(请求域:例如在tb的界面请求百度的页面,则请求域为百度,把百度的cookie发送给server,而不是把tb的cookie发送到百度的server)
- server端可以修改cookie返回给客户端,浏览器也可以通过js修改cookie传给server端,但是这里的修改是有限制的(server端有时候需要锁死一段cookie,不让js去修改)
浏览器查看cookie的三种方式:
- 请求发送以后在request中查看cookie,也可在response中查看set-cookie
- 控制台的application中的storage中查看cookie
- 在控制台打印document.cookie可以打印出cookie(有限制的,若server端设置某cookie值为httpOnly,则无法通过脚本查看这部分被限制的cookie值,因此查看cookie时第三种方法和上述两种方法相比,得到的结果是有差异的,数据有可能是少的)
node读取cookie
const cookieStr=req.headers.cookie
//cookieStr是一个字符串,格式为k1=v1;k2=v2
//解析cookie
req.cookie={}
cookieStr.split(";").forEach(item=>{
const arr=item.split("=")
const key=arr[0]
const value=arr[1]
req.cookie[key]=value
})
node写入cookie
res.setHeader("Set-Cookie",`username=${username};path=/`
这里的path=/很重要,如果不写,路由变化以后cookie是无效的
对cookie做出限制
如果不对cookie做限制,那么前端就可以用js脚本任意修改cookie的值,假如用其他人的信息随意更改本人的登录信息会造成严重的后果,因此需要对cookie做出限制res.setHeader('Set-Cookie',`username=${username};path=/;httpOnly`
在代码中加入httpOnly以后发现一个问题:正常请求接口后端写入cookie以后,前端在浏览器控制台使用document.cookie追加同样的key值时没有被后端写入的值覆盖,而是在当前cookie追加了写入的值,这显然不符合httpOnly应该起的作用。
最后打印了一下这里的key,value值,发现key值前面自动追加了一个空格
const key=arr[0]
const value=arr[1]
这里需要注意的是我们每次用document.cookie去追加cookie的时候默认会在追加值前面加一个空格,例如
Cookie: username=lisi; username=zhangsan
所以username和(空格)username是不一样的,无法用server端写入的值去覆盖前端写入的值,因此在解析cookie的时候需要对空格做一下处理
cookieStr.split(";").forEach(item=>{
const arr=item.split("=")
const key=arr[0].trim()
const value=arr[1].trim()
req.cookie[key]=value
})
三.从cookie到session
之所以有session这个概念,肯定是因为cookie暴露出了一些问题- 如果登录的时候我们直接通过cookie传递username或者一些用户的个人信息是非常危险的,因此我们需要一个映射关系,在cookie中用一个用户标识id(可以是一个随机数)映射到后端真正存储的用户信息
- cookie是有大小限制的,以kb为单位,不能存储过多的用户信息
四.从普通js对象存储session到redis存储
cpu,内存,进程
redis缓存数据库,放在内存中
优点:访问快
内存:贵,存储少,断电丢失
mysql:硬盘数据库
webserver----》redis,mysql
为什么要把session存放在redis里面,而不是放在mysql里面?
1.处理seesion的操作是在入口文件,每次程序进来都会先读取这块的代码,是非常频繁的;而mysql数据里面的增删改查是后置操作,什么时候用什么时候触发
2.sessio不考虑断电丢失的问题,丢了重新登录就行
3.session存储的数据量不是很大
Mac安装redis
brew install redis
启动redis
redis-server,成功以后就会有这个图
redis-cli
redis基本使用就是set和get
还有keys *可以看到所有设置的keys值
del myname:删除myname的值
如果遇到以下错误:
说明该进程已经占用了6379这个端口,因此无法使用redis-server启动redis,解决的方法如下:
ps -ef | grep redis
在控制台输入上述命令行可以查看目前正在被占用的端口进程:
看到6379这个端口进程为67496,如果需要继续使用这个进程,则直接在控制台输入:
redis-cli
如果不想再占用这个端口,则需要杀死这个进程:
kill -9 -67496
可以看到杀完进程以后6379端口没有再占用
此时在控制台输入 redis-server,就会出现上面那张成功的图片