@
目录前后端鉴权之session-cookie
什么是Cookie?
Cookie
就是访问者在访问网站后留下的一个信息片段。它存储在客户端(通常来说是浏览器)。你可以把cookie
当作一个map
,里边是键值对,每个键值对有过期时间、域、路径、脚本可否访问等描述信息;描述信息存储在客户端,客户端请求时,默认会带上cookie
的名称和值,不会带描述信息,通过http
请求报文header
中的cookie
项进行传输;服务器响应时,可以设置cookie
信息,就在http
响应报文的header
中Set-Cookie
项。
关于Cookie
的详细了解请参考——一文了解cookie
什么是Session?
客户端请求服务端,服务端会为这次请求开辟一块内存空间,这个对象便是 Session
对象,存储结构为 ConcurrentHashMap
。Session
弥补了 HTTP
无状态特性,服务器可以利用 Session
存储客户端在同一个会话期间的一些操作记录。
session
和 cookies
是有联系的,session
就是服务端在客户端 cookies
种下的session_id
, 服务端保存session_id
所对应的当前用户所有的状态信息。每次客户端请求服务端都带上cookies
中的session_id
, 服务端判断是否有具体的用户信息,如果没有就去调整登录。
Session 的存储方式
服务端只是给 cookie
一个 sessionId
,而 session
的具体内容(可能包含用户信息、session
状态等),要自己存一下。存储的方式有几种:
-
Redis
(推荐):内存型数据库,redis中文官方网站。以key-value
的形式存,正合sessionId-sessionData
的场景;且访问快。 - 内存:直接放到变量里。一旦服务重启就没了
- 数据库:普通数据库。性能不高。
node.js 下的 session 处理
服务端要实现对 cookie
和 session
的存取,实现起来要做的事还是很多的。在npm
中,已经有封装好的中间件,比如 express-session - npm。它主要实现了:
- 封装了对
cookie
的读写操作,并提供配置项配置字段、加密方式、过期时间等。 - 封装了对
session
的存取操作,并提供配置项配置session
存储方式(内存/redis)、存储规则等。 - 给
req
提供了session
属性,控制属性的set/get
并响应到cookie
和session
存取上,并给req.session
提供了一些方法。
简单实现
// server.js
const express = require('express')
const cookieParser = require('cookie-parser')
// 自动操作 cookie
const session = require('express-session')
// 创建服务器应用程序
const app = express()
// 公开指定目录
app.use('/public/', express.static('./public/'))
app.use(cookieParser())
app.use(session({ // 配置参数
secret: 'xiaan', // 加密口令
resave: true, // 重新储存,每一次 session 修改的时候都会从重新存储
saveUninitialized: false // 默认 true, 未初始化的时候需不需要存储内容
}))
//当服务器收到 get 请求 / 的时候, 执行回调处理函数
app.get('/index', (req, res) => {
console.log(req.session)
// 判断是否登录,如果未登录则重定向到登录
if (req.session.name !== '夏安') return res.redirect('/login')
res.send('我已经登录') // 中文框架会自动解析字符串编码格式
})
app.get('/login', function (req, res) {
req.session.name = '夏安'
res.send('请先登录')
})
app.listen(3000, () => {
console.log("http://localhost:3000");
})
缺点
-
cookies
安全性不好,攻击者可以通过获取本地cookies
进行欺骗或者利用cookies
进行CSRF
攻击。 -
cookies
在多个域名下,会存在跨域问题 -
session
的信息是保存在服务端上面的,当我们node.js
在stke
部署多台机器的时候,需要解决共享session
,所以引出来session
持久化问题,所以session
不支持分布式架构,无法支持横向扩展,只能通过数据库来保存会话数据实现共享。如果持久层失败会出现认证失败。
参考: