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-session
API
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
,如果使用HTTP
Cookie不会被设置。这时,如果使用了代理,则应该在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从不被修改。该值默认为true
rolling
- 强制在每个response中Cookie中设置session标识符。到期时间会被重置为原始的maxAge
。当此选项被设置为
true
,而saveUninitialized
设置为false
时,未初始化的session的cookie将不会在response中设置。saveUninitialized
- 强制将未初始的session保存到存储中。Session在新创建而未修改时,是未初始化状态。secret
- 必须项。该值用于session ID的cookie签名。该值可以是单个字符串,或是多个字符串数组。当使用数组时,只有第一个会被用于签名,而所有值都会被用于request中的签名。store
- session的存储实例,默认为MemoryStore
unset
-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的剩余有效期,可以对其设置一个新值以调整.expire
var 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,该方法用于向存储发送信号指定会话处于活动状态,可能会重置空闲计时器。