express-session是Express官方提供的一个用于处理Session的中间件,在Express应用中引入express-session后,可以很方便的在req.session中访问Session。
1. 使用express-session
安装
express-session可以通过npm安装:
$ npm install express-session --save
使用
安装后,可以在Experss应用的启动文件(一般是app.js)中,做为中间件引用express-session后。
通过app.use()方法引入express-session中间件:
var session = require('express-session');
// 挂载 session 中间件
app.use(session({ secret: 'a secret', cookie: { maxAge: 60000 }}));
引入express-session中间件后,就可以在其后的路由中通过req对象操作Session。
以下是一个通过Session记录访问页面访问次数的示例:
// 通过 req.session 访问 session
app.get('/', (req, res, next) => {
var sess = req.session
if (sess.views) {
sess.views++
res.setHeader('Content-Type', 'text/html')
res.write('<p>views: ' + sess.views + '</p>')
res.write('<p>expires in: ' + (sess.cookie.maxAge / 1000) + 's</p>')
res.end()
} else {
sess.views = 1
res.end('welcome to the session demo. refresh!')
}
})
2. express-sessionAPI
var session = require('express-session');
2.1 session(options)
通过指定参数对象options创建一个Session中间件。
express-session被导出为一个工厂方法,通过require引用可获取该方法,并可通过该方法创建一个Session中间件。
Session 中间件的一些说明
Session 数据并不存储在 Cookie中,而是存储在服务端,Cookie仅会存储一个session ID。
自1.5.0版本起,express-session会支持在req/res中操作Cookie,而不在依赖cookie-parser中间件。当使用cookie-parser时,应该确保两个中间件的secret一致,否则可能会出现问题。
express-session在服务端默认会使用MemoryStore存储 Session,这样在进程重启时会导致Session丢失,且不能多进程环境中传递。在生产环境中,应该使用外部存储,以确保 Session 的持久性。以下是官方推荐的一些Session存储:
2.2 Options
在使用express-session创建中间件时,我们会传入一个options对象,在这个对象中可以包含以下属性:
cookie- Object,用于设置存储session ID的Cookie,默认值是{ path: '/', httpOnly: true, secure: false, maxAge: null }cookie中可以包含以下选项cookie.domain- 指定Set-Cookie的Domain属性。默认域名不会设置,设置后,Cookie仅会对指定的域名生效。cookie.expires-Date对象,用于指定Set-Cookie的Expires属性。默认不会设置超时属性,而客户端会实现为"non-persistent cookie"。当同时设置
expires和maxAge时,将会使用后设置的一个。更推荐使用maxAge,而不显示的设置expires。cookie.httpOnly-boolean值,用于指定Set-Cookie的HttpOnly属性。默认HttpOnly属性会被设置。设置为
true时,将不允许JavaScript通过document.cookie访问Cookiecookie.maxAge-number(毫秒),用于指定Set-Cookie的Expires属性。设置后,Cookie将在指定时间后失效。cookie.path- 用于指定Set-Cookie的Path属性。默认会被设置为'/',即当前域名的根路径。cookie.sameSite-boolean或string值,用于指定Set-Cookie的SameSite属性:true时SameSite设置等同于'strict'false时将不会设置SameSite'lax'将设置SameSite为Lax,对同一站点松散执行'strict'将设置SameSite为Strict,对同一站点严格执行
cookie.secure-boolean值,用于指定Set-Cookie的Secure属性。默认情况下,不会设置该值。将设置为
true时,不使用HTTPS连接时,当客户端将不会回传Cookie。推荐使用
secure: true设置,但这时站点应该HTTPS,如果使用HTTPCookie不会被设置。这时,如果使用了代理,则应该在Expres中设置"trust proxy":var app = express() app.set('trust proxy', 1) // trust first proxy app.use(session({ secret: 'keyboard cat', resave: false, saveUninitialized: true, cookie: { secure: true } }))
genid- 一个函数,用于生成新的Session ID。该函数会将req做为第一个参数,而生成的ID,也可以添加到req上。默认情况下,会使用
uid-safe库生成ID。如果要自定义生成,可以像下面这样:app.use(session({ genid: function(req) { return genuuid() // use UUIDs for session IDs }, secret: 'keyboard cat' }))name- session ID的Cookie名,该值会设置到response中,并可在request中读取。默认值为'connect.sid'proxy- 设置安全Cookie时,信任反向代理。其默认值为
undefined,可设置值如下:true会使用"X-Forwarded-Proto"头false忽略所有请求头,只有使用TLS/SSL时才会认为是安全连接undefined使用Express中的"trust proxy"
resave- 强制将 session 保存回session存储区,即使在请求期间session从不被修改。该值默认为truerolling- 强制在每个response中Cookie中设置session标识符。到期时间会被重置为原始的maxAge。当此选项被设置为
true,而saveUninitialized设置为false时,未初始化的session的cookie将不会在response中设置。saveUninitialized- 强制将未初始的session保存到存储中。Session在新创建而未修改时,是未初始化状态。secret- 必须项。该值用于session ID的cookie签名。该值可以是单个字符串,或是多个字符串数组。当使用数组时,只有第一个会被用于签名,而所有值都会被用于request中的签名。store- session的存储实例,默认为MemoryStoreunset-req.session释放结果控制。默认为'keep':'destroy'- Session会在response结束后删除'keep'- Session会被保存在存储中,但在请求期间将不能修改和保存
2.3 Session对象
req.session - 访问Session
正确设置express-session中间件后,可以通过req.session属性来存储或访问Session数据,Session会被序列化为JSON存储。
// Use the session middleware
app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}))
// Access the session as req.session
app.get('/', function(req, res, next) {
var sess = req.session
if (sess.views) {
sess.views++
res.setHeader('Content-Type', 'text/html')
res.write('views: ' + sess.views + '
')
res.write('expires in: ' + (sess.cookie.maxAge / 1000) + 's
')
res.end()
} else {
sess.views = 1
res.end('welcome to the session demo. refresh!')
}
})
req.sessionID - 已载入Session的ID
通过req.sessionID属性,可以获取已加载的Session的ID。在Session创建/载入后,该属必是个只读值。
2.3.1 Session中的方法
Session.regenerate(callback) - 重新生成Session
调用本方法会重新生成Session。生成后,一个新的SID及session会被初始化到req.session,并且callback会被调用。
req.session.regenerate(function(err) {
// will have a new session here
})
Session.destroy(callback) - 删除Session
删除Session并重置req.session属性,完成后,callback会被调用。
req.session.destroy(function(err) {
// cannot access session here
})
Session.reload(callback) - 重新加载Session
从存储中重新加载Session,并重新填充req.session属性,完成后,callback会被调用。。
req.session.reload(function(err) {
// session updated
})
Session.save(callback) - 保存Session到存储中
保存Session到存储中,用内存中的Session替换存储中的Session内容。
当Session发生改变时,会在响应完成后,自动调用本方法。
req.session.save(function(err) {
// session saved
})
Session.touch() - 更新有效期
更新.maxAge属性,通常不需要调用本方法,因为Session中间件会自动调用。
2.3.2 Session中的属性
req.session.id - Session ID
每个Session都有个与之关联的唯一ID。本属性是req.sessionID的别名,所以也不能对其修改。
eq.session.cookie - 存储Session ID的Cookie对象
第个Session还会有一个与之对应的Cookie对象。
Cookie.maxAge- Cookie有效期req.session.cookie.maxAge会返回Cookie的剩余有效期,可以对其设置一个新值以调整.expirevar hour = 3600000 req.session.cookie.expires = new Date(Date.now() + hour) req.session.cookie.maxAge = hour
2.4 Session存储
每个Session存储必须是一个EventEmitter并实现指定的方法。以下是一些必须实现、推荐实现和可选的方法:
store.all(callback) - 可选
以数组的形式返回存储中的所有Session。callback回调形式为:callback(error, sessions)
store.destroy(sid, callback) - 必须
通过指定的Session ID(sid)销毁/删除Session,callback回调形式为:callback(error)
store.clear(callback) - 可选
从存储中删除所有Session,callback回调形式为:callback(error)
store.length(callback) - 可选
用于获取存储的中Session数量,callback回调形式为:callback(error, len)
store.get(sid, callback) - 必须
通过指定的Session ID(sid)获取Session,callback回调形式为:callback(error, session)
store.set(sid, session, callback) - 必须
将指定的Session ID(sid)的值设置为session,callback回调形式为:callback(error)
store.touch(sid, session, callback) - 推荐
本推荐方法用于能过指定的Session Id和 session来"touch"指定的Sessoin,callback回调形式为:callback(error)
本方法主要用于存储将自动删除空闲Sessoin,该方法用于向存储发送信号指定会话处于活动状态,可能会重置空闲计时器。
