express express-session 小书

简介

express-session是express中的一个处理session的中间件,能够说是express中最多见的中间件之一了.javascript

因为会话管理依赖cookie的使用,因此它的api中有不少用于控制cookie的部分.java

总的来讲express-session有以下的特色:redis

  • session管理(基本功能)
  • cookie签名
  • 可替换持久储存模块

本文中使用的版本为1.15.6.mongodb

安装

npm install express-session --save

引入&使用

const express = require('express');
const app = new express();
const expressSession = require('express-session');

// 使用express-session
app.use(expressSession({
    secret:'hello world',// cookie签名 这个属性是必须的 具体配置和`cookie-parser`同样
    saveUninitialized:true, // 是否自动初始化 默认为true
    resave:false,// 当用户session无变化的时候依然自动保存
    cookie:{ // cookie的信息具体操做和`cookie-parser`同样
        maxAge:1800000// 30分钟后过时
    },
    rolling:true// 每次请求的时候覆写cookie
}))

会话简介

express-session文档中有以下的一句说明:chrome

Note Session data is not saved in the cookie itself, just the session ID. Session data is stored server-side.

Session中包含的数据不会保存在cookie中,仅仅是在cookie中保存了一个SessionId而已.实际的session的数据保存在服务端.数据库

简单理解就是一个Map,键对应的是session id值保存在cookie中,值对应的是用户保存在服务端的数据.express

api介绍

参数

建立express-cookie参数基本分为两种.npm

  1. 针对于cookie的设置
  2. 针对于express-session的设置

cookie设置一览:api

app.use(expressSession({
    secret:'hello world', // cookie 签名必须有不然会报错
    cookie:{
        domain:<参数>,
        expires:<参数>,
        httpOnly:<参数>,
        path:<参数>,
        sameSite:<参数>,
        secure:<参数>,
        maxAge:1800000
    }
}));

而这些对应的参数就是服务端对于cookie的写入参数,至于各个参数是什么意思参考下面的文章:浏览器

https://developer.mozilla.org...

express-session部分设置:

app.use(expressSession({
    secret:'hello world', // cookie 签名必须有不然会报错
    genid:function (request) { // 用于替换掉默认ID生成的函数 第一个参数为reqeust
        return '随机id'
    },
    name:'connect.sid',// 每次响应中向cookie中起始的内容,默认起始为`connect.sid`,
    proxy:true,// 对于cookie使用secure后,在传递的过程当中相信反向代理服务器,默认为undefined只相信正向代理
    resave:true,// 在一次会话中不管是否session被改变都会进行强制的储存
    rolling:true,// 在每次会话中的响应中都覆写一次cookie,重置倒计时
    saveUninitialized:true,// 将一个新建立还未修改的会话进行储存,默认为true
    store:object// 一个储存对象,默认使用的是`MemoryStore`这个存储器
    unset:'keep'// 控制没有设置`req.session`时候的行为(使用delete删除或者赋值null),默认'keep'会话期间不会保留,'destroy'会话完成后删除.
}));

方法

request.session上挂载的session对象,除了有你添加的内容外,还有默认的方法存在:

req.session.regenerate(function(err) {
  // 调用这个方法重新生成一个新的会话,完成后触发
})
req.session.destroy(function(err) {
  // 删除这个会话,完成后触发
})
req.session.reload(function(err) {
  // 重新加载session数据,完成后触发回调
})
req.session.save(function(err) {
  // 使用当前内存中的数据保存到储存器中
  // 默认在会话结束的时候就会自动调用这个方法
})
req.session.touch() // 更新cookie中的maxAge,通常不须要手动操做,交由中间件

属性

一样的在session实例上也有不少属性:

req.session.id // 保存惟一的会话id值,不可修改
req.session.cookie // 以键值对的形式保存cookie的原始数据
req.session.cookie.maxAge // 以毫秒的形式返回剩余存活时间
req.sessionID // 保存惟一的会话id,只读

一个简单的例子

一个简单的登陆例子:

const express = require('express');
const app = new express();

const expressSession = require('express-session');


const userDb = new Map();


app.use(expressSession({
    secret:'hello world',
    saveUninitialized:true,
    resave:false,
    cookie:{
        maxAge:1800000
    },
    rolling:true,
}));


app.get('/login', (request, response) => {

    const
        id = request.query.id,
        pwd = request.query.pwd;

    if(id && pwd){

        if(userDb.has(id+pwd)){

            response.send('该用户已登陆');

        }else{

            request.session.userId = id+pwd;
            userDb.set(id+pwd,id);
            response.redirect('/');

        }

    }else{
        response.send('请输入正确的账号和密码');
    }

});

app.get('/logout',(request, response)=>{

    const userId = request.session.userId;

    request.session.destroy((err)=>{

        if(err || !userDb.has(userId)){
            response.send('登出失败');
        }else{
            userDb.delete(userId);
            response.send('登出成功');
        }

    });

});

app.get('/',(request, response)=>{


    if(request.session.userId && userDb.has(request.session.userId)){

        response.send(`欢迎回来${userDb.get(request.session.userId)}`);
    }else{

        response.send('还未登陆');
    }

});

app.use((request, response) => {

    response.send('404 not found');

});

app.listen(8888, '127.0.0.1');

在浏览器中依次输入如下url来模拟登陆行为:

localhost:8888/

localhost:8888/login?id=ASCll&pwd=123456

localhost:8888/

localhost:8888/logout

localhost:8888/

暗坑

我在chrome浏览器下运行上面的例子屡次后发现一个问题,浏览器会进行预读取网页来提升性能,也就是说在浏览器中当我url输入到以下的地方时:

localhost:8888/logo

根据我之间屡次进入这个页面浏览器会提早访问这个页面localhost:8888/logout,而致使服务器直接删除session等到真正进入到页面的时候已是第二次加载页面了,致使每次登出都显示失败.

但愿有经验的朋友能给出一个合理的解决方案.

注意

express-sessioncookie-parser一块儿使用的时候对于cookie的签名必须一致.

express-session的存储实例是能够更换的,默认使用MemoryStore只适合于测试和开发使用,生产环境必需要使用其余的储存实例,不然会出现内存碎片问题,在官方文档中给出了已经实现的接口,能够对接redis以及mongodb等数据库.

该列表在官方文档的最后:

npm地址
相关文章
相关标签/搜索