express-session
一、什么是session?
最近在学习node.js 的express框架,接触到了关于session方面的内容。翻阅了一些的博客,学到了不少东西,发现一篇博文讲的很好,概念内容摘抄如下:
Session是什么
Session一般译作会话,牛津词典对其的解释是进行某活动连续的一段时间。从不同的层面看待session,它有着类似但不全然相同的含义。比如,在web应用的用户看来,他打开浏览器访问一个电子商务网站,登录、并完成购物直到关闭浏览器,这是一个会话。而在web应用的开发者开来,用户登录时我需要创建一个数据结构以存储用户的登录信息,这个结构也叫做session。因此在谈论session的时候要注意上下文环境。而本文谈论的是一种基于HTTP协议的用以增强web应用能力的机制或者说一种方案,它不是单指某种特定的动态页面技术,而这种能力就是保持状态,也可以称作保持会话。
为什么需要session
谈及session一般是在web应用的背景之下,我们知道web应用是基于HTTP协议的,而HTTP协议恰恰是一种无状态协议。也就是说,用户从A页面跳转到B页面会重新发送一次HTTP请求,而服务端在返回响应的时候是无法获知该用户在请求B页面之前做了什么的。
对于HTTP的无状态性的原因,相关RFC里并没有解释,但联系到HTTP的历史以及应用场景,我们可以推测出一些理由:
1. 设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。那个时候没有动态页面技术,只有纯粹的静态HTML页面,因此根本不需要协议能保持状态;
2. 用户在收到响应时,往往要花一些时间来阅读页面,因此如果保持客户端和服务端之间的连接,那么这个连接在大多数的时间里都将是空闲的,这是一种资源的无端浪费。所以HTTP原始的设计是默认短连接,即客户端和服务端完成一次请求和响应之后就断开TCP连接,服务器因此无法预知客户端的下一个动作,它甚至都不知道这个用户会不会再次访问,因此让HTTP协议来维护用户的访问状态也全然没有必要;
3. 将一部分复杂性转嫁到以HTTP协议为基础的技术之上可以使得HTTP在协议这个层面上显得相对简单,而这种简单也赋予了HTTP更强的扩展能力。事实上,session技术从本质上来讲也是对HTTP协议的一种扩展。
总而言之,HTTP的无状态是由其历史使命而决定的。但随着网络技术的蓬勃发展,人们再也不满足于死板乏味的静态HTML,他们希望web应用能动起来,于是客户端出现了脚本和DOM技术,HTML里增加了表单,而服务端出现了CGI等等动态技术。
而正是这种web动态化的需求,给HTTP协议提出了一个难题:一个无状态的协议怎样才能关联两次连续的请求呢?也就是说无状态的协议怎样才能满足有状态的需求呢?
此时有状态是必然趋势而协议的无状态性也是木已成舟,因此我们需要一些方案来解决这个矛盾,来保持HTTP连接状态,于是出现了cookie和session。
对于此部分内容,读者或许会有一些疑问,笔者在此先谈两点:
1. 无状态性和长连接
可能有人会问,现在被广泛使用的HTTP1.1默认使用长连接,它还是无状态的吗?
连接方式和有无状态是完全没有关系的两回事。因为状态从某种意义上来讲就是数据,而连接方式只是决定了数据的传输方式,而不能决定数据。长连接是随着计算机性能的提高和网络环境的改善所采取的一种合理的性能上的优化,一般情况下,web服务器会对长连接的数量进行限制,以免资源的过度消耗。
2. 无状态性和session
Session是有状态的,而HTTP协议是无状态的,二者是否矛盾呢?
Session和HTTP协议属于不同层面的事物,后者属于ISO七层模型的最高层应用层,前者不属于后者,前者是具体的动态页面技术来实现的,但同时它又是基于后者的。在下文中笔者会分析Servlet/Jsp技术中的session机制,这会使你对此有更深刻的理解。
Cookie和Session
上面提到解决HTTP协议自身无状态的方式有cookie和session。二者都能记录状态,前者是将状态数据保存在客户端,后者则保存在服务端。
首先看一下cookie的工作原理,这需要有基本的HTTP协议基础。
cookie是在RFC2109(已废弃,被RFC2965取代)里初次被描述的,每个客户端最多保持三百个cookie,每个域名下最多20个Cookie(实际上一般浏览器现在都比这个多,如Firefox是50个),而每个cookie的大小为最多4K,不过不同的浏览器都有各自的实现。对于cookie的使用,最重要的就是要控制cookie的大小,不要放入无用的信息,也不要放入过多信息。
无论使用何种服务端技术,只要发送回的HTTP响应中包含如下形式的头,则视为服务器要求设置一个cookie:
|
|
支持cookie的浏览器都会对此作出反应,即创建cookie文件并保存(也可能是内存cookie),用户以后在每次发出请求时,浏览器都要判断当前所有的cookie中有没有没失效(根据expires属性判断)并且匹配了path属性的cookie信息,如果有的话,会以下面的形式加入到请求头中发回服务端:
|
|
服务端的动态脚本会对其进行分析,并做出相应的处理,当然也可以选择直接忽略。
这里牵扯到一个规范(或协议)与实现的问题,简单来讲就是规范规定了做成什么样子,那么实现就必须依据规范来做,这样才能互相兼容,但是各个实现所使用的方式却不受约束,也可以在实现了规范的基础上超出规范,这就称之为扩展了。无论哪种浏览器,只要想提供cookie的功能,那就必须依照相应的RFC规范来实现。所以这里服务器只管发Set-cookie头域,这也是HTTP协议无状态性的一种体现。
需要注意的是,出于安全性的考虑,cookie可以被浏览器禁用。
再看一下session的原理:
笔者没有找到相关的RFC,因为session本就不是协议层面的事物。它的基本原理是服务端为每一个session维护一份会话信息数据,而客户端和服务端依靠一个全局唯一的标识来访问会话信息数据。用户访问web应用时,服务端程序决定何时创建session,创建session可以概括为三个步骤:
1. 生成全局唯一标识符(sessionid);
2. 开辟数据存储空间。一般会在内存中创建相应的数据结构,但这种情况下,系统一旦掉电,所有的会话数据就会丢失,如果是电子商务网站,这种事故会造成严重的后果。不过也可以写到文件里甚至存储在数据库中,这样虽然会增加I/O开销,但session可以实现某种程度的持久化,而且更有利于session的共享;
3. 将session的全局唯一标示符发送给客户端。
问题的关键就在服务端如何发送这个session的唯一标识上。联系到HTTP协议,数据无非可以放到请求行、头域或Body里,基于此,一般来说会有两种常用的方式:cookie和URL重写。
|
|
Cookie和session由于实现手段不同,因此也各有优缺点和各自的应用场景:
1. 应用场景
Cookie的典型应用场景是Remember Me服务,即用户的账户信息通过cookie的形式保存在客户端,当用户再次请求匹配的URL的时候,账户信息会被传送到服务端,交由相应的程序完成自动登录等功能。当然也可以保存一些客户端信息,比如页面布局以及搜索历史等等。
Session的典型应用场景是用户登录某网站之后,将其登录信息放入session,在以后的每次请求中查询相应的登录信息以确保该用户合法。当然还是有购物车等等经典场景;
2. 安全性
cookie将信息保存在客户端,如果不进行加密的话,无疑会暴露一些隐私信息,安全性很差,一般情况下敏感信息是经过加密后存储在cookie中,但很容易就会被窃取。而session只会将信息存储在服务端,如果存储在文件或数据库中,也有被窃取的可能,只是可能性比cookie小了太多。
Session安全性方面比较突出的是存在会话劫持的问题,这是一种安全威胁,这在下文会进行更详细的说明。总体来讲,session的安全性要高于cookie;
3. 性能
Cookie存储在客户端,消耗的是客户端的I/O和内存,而session存储在服务端,消耗的是服务端的资源。但是session对服务器造成的压力比较集中,而cookie很好地分散了资源消耗,就这点来说,cookie是要优于session的;
4. 时效性
Cookie可以通过设置有效期使其较长时间内存在于客户端,而session一般只有比较短的有效期(用户主动销毁session或关闭浏览器后引发超时);
5. 其他
Cookie的处理在开发中没有session方便。而且cookie在客户端是有数量和大小的限制的,而session的大小却只以硬件为限制,能存储的数据无疑大了太多。
二、 express-session的安装
Installation
$ npm install express-session
API
var session = require('express-session')
session(options)
Create a session middleware with the given options.
Note
Session data is not saved in the cookie itself, just the session ID. Session data is stored server-side.
Note
Since version 1.5.0, the cookie-parser middleware no longer needs to be used for this module to work. This module now directly reads and writes cookies on req/res. Using cookie-parser may result in issues if the secret is not the same between this module and cookie-parser.
Warning
The default server-side session storage, MemoryStore, is purposely not designed for a production environment. It will leak memory under most conditions, does not scale past a single process, and is meant for debugging and developing.
For a list of stores, see compatible session stores.
Options
express-session accepts these properties in the options object.
cookie
Settings object for the session ID cookie. The default value is { path: '/', httpOnly: true, secure: false, maxAge: null }.
The following are options that can be set in this object.
cookie.domain
Specifies the value for the Domain Set-Cookie
attribute. By default, no domain is set, and most clients will consider the cookie to apply to only the current domain.
cookie.expires
Specifies the Date
object to be the value for the Expires Set-Cookie
attribute. By default, no expiration is set, and most clients will consider this a “non-persistent cookie” and will delete it on a condition like exiting a web browser application.
Note
If both expires
and maxAge
are set in the options, then the last one defined in the object is what is used.
Note
The expires
option should not be set directly;
instead only use the maxAge option.
cookie.httpOnly
Specifies the boolean
value for the HttpOnly Set-Cookie
attribute. When truthy, the HttpOnly attribute is set, otherwise it is not. By default, the HttpOnly
attribute is set.
Note
be careful when setting this to true
, as compliant clients will not allow client-side JavaScript to see the cookie in document.cookie
.
cookie.maxAge
Specifies the number (in milliseconds) to use when calculating the Expires Set-Cookie
attribute. This is done by taking the current server time and adding maxAge milliseconds to the value to calculate an Expires
datetime. By default, no maximum age is set.
Note
If both expires
and maxAge
are set in the options, then the last one defined in the object is what is used.
cookie.path
Specifies the value for the Path Set-Cookie
. By default, this is set to ‘/‘, which is the root path of the domain.
cookie.sameSite
Specifies the boolean or string to be the value for the SameSite Set-Cookie attribute.
- true will set the SameSite attribute to Strict for strict same site enforcement.
- false will not set the SameSite attribute.
- ‘lax’ will set the SameSite attribute to Lax for lax same site enforcement.
- ‘strict’ will set the SameSite attribute to Strict for strict same site enforcement.
More information about the different enforcement levels can be found in the specification https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-4.1.1
Note
This is an attribute that has not yet been fully standardized, and may change in the future. This also means many clients may ignore this attribute until they understand it.
cookie.secure
Specifies the boolean value for the Secure Set-Cookie
attribute. When truthy, the Secure attribute is set, otherwise it is not. By default, the Secure attribute is not set.
Note be careful when setting this to true, as compliant clients will not send the cookie back to the server in the future if the browser does not have an HTTPS connection.
Please note that secure: true is a recommended option. However, it requires an https-enabled website, i.e., HTTPS is necessary for secure cookies. If secure is set, and you access your site over HTTP, the cookie will not be set. If you have your node.js behind a proxy and are using secure: true, you need to set “trust proxy” in express:
var app = express()
app.set('trust proxy', 1) // trust first proxy
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}))
For using secure cookies in production, but allowing for testing in development, the following is an example of enabling this setup based on NODE_ENV in express:
var app = express()
var sess = {
secret: 'keyboard cat',
cookie: {}
}
if (app.get('env') === 'production') {
app.set('trust proxy', 1) // trust first proxy
sess.cookie.secure = true // serve secure cookies
}
app.use(session(sess))
The cookie.secure
option can also be set to the special value 'auto'
to have this setting automatically match the determined security of the connection. Be careful when using this setting if the site is available both as HTTP and HTTPS, as once the cookie is set on HTTPS, it will no longer be visible over HTTP. This is useful when the Express "trust proxy"
setting is properly setup to simplify development vs production configuration.
genid
Function to call to generate a new session ID. Provide a function that returns a string that will be used as a session ID. The function is given req as the first argument if you want to use some value attached to req when generating the ID.
The default value is a function which uses the uid-safe library to generate IDs.
NOTE
be careful to generate unique IDs so your sessions do not conflict.
app.use(session({
genid: function(req) {
return genuuid() // use UUIDs for session IDs
},
secret: 'keyboard cat'
}))
name
The name of the session ID cookie to set in the response (and read from in the request).
The default value is 'connect.sid'
.
Note
if you have multiple apps running on the same hostname (this is just the name, i.e. localhost or 127.0.0.1;
different schemes and ports do not name a different hostname), then you need to separate the session cookies from each other. The simplest method is to simply set different names per app.
proxy
Trust the reverse proxy when setting secure cookies (via the “X-Forwarded-Proto” header).
The default value is undefined
.
- true The “X-Forwarded-Proto” header will be used.
- false All headers are ignored and the connection is considered secure only if there is a direct TLS/SSL connection.
- undefined Uses the “trust proxy” setting from express
resave
Forces the session to be saved back to the session store, even if the session was never modified during the request. Depending on your store this may be necessary, but it can also create race conditions where a client makes two parallel requests to your server and changes made to the session in one request may get overwritten when the other request ends, even if it made no changes (this behavior also depends on what store you’re using).
The default value is true
, but using the default has been deprecated, as the default will change in the future. Please research into this setting and choose what is appropriate to your use-case. Typically, you’ll want false
.
How do I know if this is necessary for my store? The best way to know is to check with your store if it implements the touch method. If it does, then you can safely set resave: false
. If it does not implement the touch
method and your store sets an expiration date on stored sessions, then you likely need resave: true
.
rolling
Force a session identifier cookie to be set on every response. The expiration is reset to the original maxAge, resetting the expiration countdown.
The default value is false.
Note
When this option is set to true but the saveUninitialized option is set to false, the cookie will not be set on a response with an uninitialized session.
saveUninitialized
Forces a session that is “uninitialized” to be saved to the store. A session is uninitialized when it is new but not modified. Choosing false
is useful for implementing login sessions, reducing server storage usage, or complying with laws that require permission before setting a cookie. Choosing false
will also help with race conditions where a client makes multiple parallel requests without a session.
The default value is true, but using the default has been deprecated, as the default will change in the future. Please research into this setting and choose what is appropriate to your use-case.
Note
if you are using Session in conjunction with PassportJS, Passport will add an empty Passport object to the session for use after a user is authenticated, which will be treated as a modification to the session, causing it to be saved. This has been fixed in PassportJS 0.3.0
secret
Required option
This is the secret used to sign the session ID cookie. This can be either a string for a single secret, or an array of multiple secrets. If an array of secrets is provided, only the first element will be used to sign the session ID cookie, while all the elements will be considered when verifying the signature in requests.
store
The session store instance, defaults to a new MemoryStore
instance.
unset
Control the result of unsetting req.session (through delete, setting to null, etc.).
The default value is 'keep'
.
'destroy'
The session will be destroyed (deleted) when the response ends.'keep'
The session in the store will be kept, but modifications made during the request are ignored and not saved.
req.session
To store or access session data, simply use the request property req.session
, which is (generally) serialized as JSON by the store, so nested objects are typically fine. For example below is a user-specific view counter:
// 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('<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!')
}
})
Session.regenerate(callback)
To regenerate the session simply invoke the method. Once complete, a new SID and Session instance will be initialized at req.session and the callback will be invoked.
req.session.regenerate(function(err) {
// will have a new session here
})
Session.destroy(callback)
Destroys the session and will unset the req.session property. Once complete, the callback will be invoked.
req.session.destroy(function(err) {
// cannot access session here
})
Session.reload(callback)
Reloads the session data from the store and re-populates the req.session
object. Once complete, the callback will be invoked.
req.session.reload(function(err) {
// session updated
})
Session.save(callback)
Save the session back to the store, replacing the contents on the store with the contents in memory (though a store may do something else–consult the store’s documentation for exact behavior).
This method is automatically called at the end of the HTTP response if the session data has been altered (though this behavior can be altered with various options in the middleware constructor). Because of this, typically this method does not need to be called.
There are some cases where it is useful to call this method, for example, long- lived requests or in WebSockets.
req.session.save(function(err) {
// session saved
})
Session.touch()
Updates the .maxAge
property. Typically this is not necessary to call, as the session middleware does this for you.
req.session.id
Each session has a unique ID associated with it. This property will contain the session ID and cannot be modified.
req.session.cookie
Each session has a unique cookie object accompany it. This allows you to alter the session cookie per visitor. For example we can set req.session.cookie.expires
to false to enable the cookie to remain for only the duration of the user-agent.
Cookie.maxAge
Alternatively req.session.cookie.maxAge
will return the time remaining in milliseconds, which we may also re-assign a new value to adjust the .expires property appropriately. The following are essentially equivalent
var hour = 3600000
req.session.cookie.expires = new Date(Date.now() + hour)
req.session.cookie.maxAge = hour
For example when maxAge is set to 60000 (one minute), and 30 seconds has elapsed it will return 30000 until the current request has completed, at which time req.session.touch() is called to reset req.session.maxAge to its original value.
req.session.cookie.maxAge // => 30000
req.sessionID
To get the ID of the loaded session, access the request property req.sessionID. This is simply a read-only value set when a session is loaded/created.
Session Store Implementation
Every session store must be an EventEmitter and implement specific methods. The following methods are the list of
required, recommended, and optional.
- Required methods are ones that this module will always call on the store.
- Recommended methods are ones that this module will call on the store if available.
- Optional methods are ones this module does not call at all, but helps present uniform stores to users.
For an example implementation view the connect-redis repo.
store.all(callback)
Optional
This optional method is used to get all sessions in the store as an array. The callback should be called as callback(error, sessions).
store.destroy(sid, callback)
Required
This required method is used to destroy/delete a session from the store given a session ID (sid)
. The callback
should be called as callback(error)
once the session is destroyed.
store.clear(callback)
Optional
This optional method is used to delete all sessions from the store. The callback
should be called as callback(error)
once the store is cleared.
store.length(callback)
Optional
This optional method is used to get the count of all sessions in the store. The callback
should be called as callback(error, len)
.
store.get(sid, callback)
Required
This required method is used to get a session from the store given a session ID (sid)
. The callback
should be called as callback(error, session)
.
The session
argument should be a session if found, otherwise null or undefined if the session was not found (and there was no error). A special case is made when error.code === 'ENOENT'
to act like callback(null, null)
.
store.set(sid, session, callback)
Required
This required method is used to upsert a session into the store given a session ID (sid) and session (session
) object. The callback should be called as callback(error)
once the session has been set in the store.
store.touch(sid, session, callback)
Recommended
This recommended method is used to “touch” a given session given a session ID (sid
) and session (session
) object. The callback should be called as callback(error)
once the session has been touched.
This is primarily used when the store will automatically delete idle sessions and this method is used to signal to the store the given session is active, potentially resetting the idle timer.
Compatible Session Stores
The following modules implement a session store that is compatible with this module. Please make a PR to add additional modules :)
aerospike-session-store A session store using Aerospike.
cassandra-store An Apache Cassandra-based session store.
cluster-store A wrapper for using in-process / embedded stores - such as SQLite (via knex), leveldb, files, or memory - with node cluster (desirable for Raspberry Pi 2 and other multi-core embedded devices).
connect-azuretables An Azure Table Storage-based session store.
[connect-couchbase] (https://www.npmjs.com/package/connect-couchbase)A couchbase-based session store.
connect-datacache An IBM Bluemix Data Cache-based session store.
connect-db2 An IBM DB2-based session store built using ibm_db module.
connect-dynamodb A DynamoDB-based session store.
connect-loki A Loki.js-based session store.
connect-ml A MarkLogic Server-based session store.
connect-mssql A SQL Server-based session store.
connect-monetdb A MonetDB-based session store.
connect-mongo A MongoDB-based session store.
connect-mongodb-session Lightweight MongoDB-based session store built and maintained by MongoDB.
connect-pg-simple A PostgreSQL-based session store.
connect-redis A Redis-based session store.
connect-memcached A memcached-based session store.
connect-session-knex A session store using Knex.js, which is a SQL query builder for PostgreSQL, MySQL, MariaDB, SQLite3, and Oracle.
connect-session-sequelize A session store using Sequelize.js, which is a Node.js / io.js ORM for PostgreSQL, MySQL, SQLite and MSSQL.
express-mysql-session A session store using native MySQL via the node-mysql module.
express-sessions: A session store supporting both MongoDB and Redis.
connect-sqlite3 A SQLite3session store modeled after the TJ’s connect-redis store.
documentdb-sessionA session store for Microsoft Azure’s DocumentDB NoSQL database service.
express-nedb-session A NeDB-based session store.
express-session-level A LevelDB based session store.
express-etcd An etcd based session store.
hazelcast-store A Hazelcast-based session store built on the Hazelcast Node Client.
[level-session-store] A LevelDB-based session store.
medea-session-store A Medea-based session store.
mssql-session-store A SQL Server-based session store.
nedb-session-store An alternate NeDB-based (either in-memory or file-persisted) session store.
sequelstore-connect A session store using Sequelize.js.
session-file-storeA file system-based session store.
session-rethinkdb* A RethinkDB-based session store.
Example
A simple example using express-session to store page views for a user.
express框架之session 内存存储
1 var express = require('express');
2 var session = require('express-session');
3 var cookieParser = require('cookie-parser');
4
5 var app = express();
6
7 app.use(cookieParser());
8 app.use(session({
9 secret: '12345',
10 name: 'testapp', //这里的name值得是cookie的name,默认cookie的name是:connect.sid
11 cookie: {maxAge: 80000 }, //设置maxAge是80000ms,即80s后session和相应的cookie失效过期
12 resave: false,
13 saveUninitialized: true,
14 }));
15
16
17 app.get('/awesome', function(req, res){
18
19 if(req.session.lastPage) {
20 console.log('Last page was: ' + req.session.lastPage + ".");
21 }
22 req.session.lastPage = '/awesome'; //每一次访问时,session对象的lastPage会自动的保存或更新内存中的session中去。
23 res.send("You're Awesome. And the session expired time is: " + req.session.cookie.maxAge);
24 });
25
26 app.get('/radical', function(req, res){
27 if (req.session.lastPage) {
28 console.log('Last page was: ' + req.session.lastPage + ".");
29 }
30 req.session.lastPage = '/radical';
31 res.send('What a radical visit! And the session expired time is: ' + req.session.cookie.maxAge);
32 });
33
34 app.get('/tubular', function(req, res){
35 if (req.session.lastPage){
36 console.log("Last page was: " + req.session.lastPage + ".");
37 }
38
39 req.session.lastPage = '/tubular';
40 res.send('Are you a suffer? And the session expired time is: ' + req.session.cookie.maxAge);
41 });
42
43
44 app.listen(5000);
express框架之session 数据库存储
有时候,我们需要session的声明周期要长一点,比如好多网站有个免密码两周内自动登录的功能。基于这个需求,session必须寻找内存之外的存储载体,数据库能提供完美的解决方案。这里,我选用的是mongodb数据库,作为一个NoSQL数据库,它的基础数据对象时database-collection-document 对象模型非常直观并易于理解,针对node.js 也提供了丰富的驱动和API。express框架提供了针对mongodb的中间件:connect-mongo,我们只需在挂载session的时候在options中传入mongodb的参数即可,程序运行的时候, express app 会自动的替我们管理session的存储,更新和删除。具体可以参考:
https://github.com/kcbanner/connect-mongo
1 var express = require('express');
2 var session = require('express-session');
3 var cookieParser = require('cookie-parser');
4 var MongoStore = require('connect-mongo')(session);
5 var app = express();
6
7 app.use(cookieParser());
8 app.use(session({
9 secret: '12345',
10 name: 'testapp',
11 cookie: {maxAge: 80000 },
12 resave: false,
13 saveUninitialized: true,
14 store: new MongoStore({ //创建新的mongodb数据库
15 host: 'localhost', //数据库的地址,本机的话就是127.0.0.1,也可以是网络主机
16 port: 27017, //数据库的端口号
17 db: 'test-app' //数据库的名称。
18 })
19 }));
20
21
22 app.get('/awesome', function(req, res){
23
24 if(req.session.lastPage) {
25 console.log('Last page was: ' + req.session.lastPage + ".");
26 }
27 req.session.lastPage = '/awesome';
28 res.send("You're Awesome. And the session expired time is: " + req.session.cookie.maxAge);
29 });
30
31 app.get('/radical', function(req, res){
32 if (req.session.lastPage) {
33 console.log('Last page was: ' + req.session.lastPage + ".");
34 }
35 req.session.lastPage = '/radical';
36 res.send('What a radical visit! And the session expired time is: ' + req.session.cookie.maxAge);
37 });
38
39 app.get('/tubular', function(req, res){
40 if (req.session.lastPage){
41 console.log("Last page was: " + req.session.lastPage + ".");
42 }
43
44 req.session.lastPage = '/tubular';
45 res.send('Are you a suffer? And the session expired time is: ' + req.session.cookie.maxAge);
46 });
47
48
49 app.listen(5000);
session的生命周期:
由于session是存在服务器端数据库的,所以的它的生命周期可以持久化,而不仅限于浏览器关闭的时间。具体是由cookie.maxAge 决定:如果maxAge设定是1个小时,那么从这个因浏览器访问服务器导致session创建开始后,session会一直保存在服务器端,即使浏览器关闭,session也会继续存在。如果此时服务器宕机,只要开机后数据库没发生不可逆转的破坏,maxAge时间没过期,那么session是可以继续保持的。
当maxAge时间过期后,session会自动的数据库中移除,对应的还有浏览器的cookie。不过,由于connect-mongo的特殊机制(每1分钟检查一次过期session),session的移除可能在时间上会有一定的滞后。
部分参考:https://www.npmjs.com/package/express-session#cookiemaxage