当maxAge设置为60000,也就是一分钟,这时候如果已经过去了30s,那么maxAge就会返回30000(不过要等到当前请求结束)。如果这时候我们调用req.session.touch(),那么req.session.maxAge就成了初始值了60000了
req.sessionID:
只读的属性。每一个session store必须是一个EventEmitter对象,同时要实现特定的方法。我们看看MemoryStore把:
function MemoryStore() { Store.call(this) this.sessions = Object.create(null) } //继承了Store中的所有的原型属性 util.inherits(MemoryStore, Store)
也就是说MemoryStore继承了通用的Store的所有的属性和方法,如regenerate,load,createSession,当然也实现了很多自己的方法如all,clear,destroy,get,length,set,touch等
下面讨论的是一些其他的方法:
required方法表示:在这个store上一定会调用的方法
Recommended方法表示如果有这个方法那么在这个store上就会调用。Optional方法表示不会调用,但是为了给用户一个统一的store!
store.destroy(sid, callback)
必须的方法。通过sessionID来销毁session,如果session已经被销毁,那么回调函数被调用,同时传入一个error对象
store.get(sid, callback)
必须的方法。通过sessionID从store中获取session。回调函数是callback(err,session)。如果session存在那么第二个参数就是session,否则第二个参数就是null/undefined。如果error.code==="ENOENT"那么回调为callback(null,null)
store.set(sid, session, callback)
必须的方法。如果被成功设置了那么回调为callback(error)
store.touch(sid, session, callback)
推荐的方法。通过一个指定的sid和session对象去”接触“这个session.如果接触到了那么回调为callback(error)。session store用这个方法去删除那些空闲的session。同时这个方法也会通知session store指定的session是活动态的。MemoryStore实现了这个方法:
//通过指定的sessionId获取当前的session对象,然后把这个对象的cookie更新为新的session对应的cookie,同时sessions中的当前session也进行更新(包括过期时间等) MemoryStore.prototype.touch = function touch(sessionId, session, callback) { var currentSession = getSession.call(this, sessionId) if (currentSession) { // update expiration currentSession.cookie = session.cookie this.sessions[sessionId] = JSON.stringify(currentSession) } callback && defer(callback) }
store.length(callback)
可选的方法。获取store中所有的session的个数,回调函数为callback(error,length)
store.clear(callback)
可选的方法,从store中吧所有的session都删除,回调函数为callback(err)
store.all(callback)
可选的方法。以一个数组的方法获取store中的sessions。callback(error,sessions)
session({ secret: settings.cookieSecret, //blog=s%3AisA3_M-Vso0L_gHvUnPb8Kw9DohpCCBJ.OV7p42pL91uM3jueaJATpZdlIj%2BilgxWoD8HmBSLUSo //其中secret如果是一个string,那么就是用这个string对sessionID对应的cookie进行签名,如果是一个数组那么只有第一个用于签名,其他用于浏览器请求后的验证 key: settings.db, //设置的cookie的名字,从上面可以看到这里指定的是blog,所以浏览器的请求中可以看到这里的sessionID已经不是sessionID了,而是这里的blog name:"qinliang",//name的优先级比key要高,如果同时设置了那么就是按照name来制定的 //没有name时候response中为:set-cookie:blog=s%3A6OJEWycwVMmTGXcZqawrW0HNLOTJkYKm.0Slax72TMfW%2B4Tiit3Ox7NAj5S6rPWvMUr6sY02l0DE; Path=https://www.jb51.net/; Expires=Thu, 28 Apr 2016 10:47:13 GMT; HttpOnly //当有name的时候resopnse中:set-cookie:qinliang=s%3ABDOjujVhV0DH9Atax_gl4DgZ4-1RGvjQ.OeUddoRalzB4iSmUHcE8oMziad4Ig7jUT1REzGcYcdg; Path=https://www.jb51.net/; Expires=Thu, 28 Apr 2016 10:48:26 GMT; HttpOnly resave:true,//没有实现touch方法,同时也设置了session的过期时间为30天 rolling:true,//如果设置了rolling为true,同时saveUninitialized为true,那么每一个请求都会发送没有初始化的session! saveUninitialized:false,//设置为true,存储空间浪费,不允许权限管理 cookie: { maxAge: 1000 * 60 * 60 * 24 * 30 }, //cookie里面全部的设置都是对于sessionID的属性的设置,默认的属性为{ path: 'https://www.jb51.net/', httpOnly: true, secure: false, maxAge: null }. //所以最后我们保存到数据库里面的信息就是:{"cookie":{"originalMaxAge":2592000000,"expires":"2016-04-27T02:30:51.713Z","httpOnly":true,"path":"https://www.jb51.net/"},"flash":{}} store: new MongoStore({ db: settings.db, host: settings.host, port: settings.port }) })
从源码的角度来分析配置项:
(1)这里面的secret到底有什么用呢?
我们看看这个express-session到底是如何做的?