Cookie和Session
1. HTTP协议的无状态性
- HTTP协议的通信模型:基于
请求 - 处理 - 响应
的! - 由于这个通信协议的关系,导致了HTTP每个请求之间都是没有关联的,每当一个请求完成之后,服务器就忘记之前谁曾经请求过!
- 如果纯粹基于HTTP通信模型,是无法完成登录状态保持的!每次请求服务器,服务器都会把这个请求当作新请求来处理!
- 我们可以通过 cookie 技术,实现状态保持,但是由于cookie是存储在客户端的一门技术,所以安全性几乎没有,因此不要使用cookie存储敏感的数据!
2. cookie介绍
2.1 什么是cookie,作用是什么
-
由于Http协议是无状态的,且传统服务器只能被动的响应请求,所以,当服务器获取到请求的时候,并不知道当前请求属于哪个客户端!
-
服务器为了能够明确区分每个客户端,需要使用一些小技术,来根据不同的请求区分不同的客户端;
-
只要有请求发生,那么必然对应一个客户端,我们可以在每次客户端发起请求的时候,向服务器自动发送一个标识符,告诉服务器当前是哪个客户端正在请求服务器的数据;
-
如何提供这个标识符呢?我们可以在请求头(Request Headers)中添加一个标签,叫做
cookie
,这样,每次发送请求,都会把这个cookie随同其他报文一起发送给服务器,服务器可以根据报文中的cookie,区分不同的客户端浏览器。 -
如何在客户端请求头中添加标识符?
-
在Node中可以在
writeHeader
的时候,通过Set-Cookie
来将cookie标识通过响应报文发送给客户端! -
客户端也可以通过一些方式来操作自己的cookie,比如通过
jquery.cookie
这个插件!
2.2 cookie的基本使用
/**
* 定义:什么是cookie呢。cookie就是存储在客户端的一小段文本;
* cookie是一门客户端的技术,因为 cookie 是存储在客户端浏览器中的;
* cookie 的作用,是为了实现 客户端与 服务器端之间的状态保持;
* cookie 技术,不安全,不要使用 cookie 保持敏感信息;
* cookie 默认,在浏览器页面关闭之后,就立即失效了;如果想指定 cookie 的过期时间,需要通过 expires 属性来实现
*/
const http = require('http')
const server = http.createServer()
/**
* 需求:如果客户端是第一次请求 服务器,就返回文本 "送你一朵小红花"
* 如果不是第一次请求服务器,就返回文本 "不要太贪心"
*/
server.on('request', (req, res) => {
if (req.url === '/') {
// 每次客户端请求服务器,我们都可以解析一下请求头中,是否携带了 cookie,如果携带了cookie,则把 cookie 解析出来,解析为一个对象;
const cookie = {}
req.headers.cookie &&
req.headers.cookie.split('; ').forEach(item => {
const parts = item.split('=')
cookie[parts[0]] = parts[1]
});
if (cookie.isvisit === 'yes') {
//客户端之前曾经访问过服务器
res.writeHeader(200, {
'Content-Type': 'text/html; charset=utf-8'
})
res.end('不要太贪心')
} else {
// 客户端之前没有访问过服务器【设置Cookie过期时间:10秒】
const expiresTime = new Date(Date.now() + 10 * 1000).toUTCString()
res.writeHeader(200, {
'Content-Type': 'text/html; charset=utf-8',
'Set-Cookie': ['isvisit=yes; expires=' + expiresTime, 'test=ook']
})
res.end('送你一朵小红花')
}
} else {
res.end('404')
}
})
server.listen(4321, () => {
console.log('server running at http://127.0.0.1:4321')
})
2.3 通过expires
设置Cookie的过期时间
// 设置 过期时间 为60秒之后
// 注意:在设置过期时间的时候,需要将时间转换为 UTC 格式
var expiresTime = new Date(Date.now() + 1000 * 60).toUTCString();
res.writeHeader(200, {
'Content-Type': 'text/html; charset=utf-8',
'Set-Cookie': ['isvisit=true;expires=' + expiresTime, 'test=OK']
});
res.end('<h3>你好,欢迎光临,送给你一个苹果!</h3>');
2.4 cookie可以被伪造,不安全
使用谷歌插件edit this cookie
,就能伪造cookie数据!所以不要使用cookie存储敏感的数据!比如登录状态和登录信息;
一些敏感的数据,应该存储都服务器端!
2.5 什么是Cookie的应用场景
- 对安全性要求不高
- 不需要存储大量的数据
- 主要应用场景,是用来做 客户端 与 服务器之间的 状态保持技术;
3. 登录退出及状态保存
3.1 使用express-session
来保存登录状态
3.1.1 什么是session
由于HTTP是无状态的,所以服务器在每次连接中持续保存客户端的私有数据,此时需要结合cookie技术,通过session会话机制,在服务器端保存每个HTTP请求的私有数据;
3.1.2 session原理
在服务器内存中开辟一块地址空间,专门存放每个客户端私有的数据,每个客户端根据cookie中保存的私有sessionId,可以获取到独属于自己的session数据。
3.1.3 在express中使用session
- 安装session模块
npm install express-session -S
- 导入session模块
var session = require('express-session')
- 在express中使用
session
中间件:
// 启用 session 中间件
app.use(session({
secret: 'keyboard cat', // 相当于是一个加密密钥,值可以是任意字符串
resave: false, // 强制session保存到session store中
saveUninitialized: false // 强制没有“初始化”的session保存到storage中
}))
- 将私有数据保存到当前请求的session会话中:
// 将登录的用户保存到session中
req.session.user = result.dataValues;
// 设置是否登录为true
req.session.islogin = true;
- 通过
destroy()
方法清空session
数据:
req.session.destroy(function(err){
if(err) throw err;
console.log('用户退出成功!');
// 实现服务器端的跳转,这个对比于 客户端跳转
res.redirect('/');
});
数据:
req.session.destroy(function(err){
if(err) throw err;
console.log('用户退出成功!');
// 实现服务器端的跳转,这个对比于 客户端跳转
res.redirect('/');
});