express express-session的使用小结


Posted in Javascript onDecember 12, 2018

简介

express-session是express中的一个处理session的中间件,可以说是express中最常见的中间件之一了.

由于会话管理依赖cookie的使用,所以它的api中有很多用于控制cookie的部分.

总的来说express-session有如下的特点:

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

本文中使用的版本为1.15.6.

安装

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文档中有如下的一句说明:

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中,值对应的是用户保存在服务端的数据.

api介绍

参数

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

  • 针对于cookie的设置
  • 针对于express-session的设置

cookie设置一览:

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

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

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Set-Cookie

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地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript 私有成员分析
Jan 13 Javascript
js报$ is not a function 的问题的解决方法
Jan 20 Javascript
当达到输入长度时表单自动切换焦点
Apr 06 Javascript
js闭包实例汇总
Nov 09 Javascript
原生javascript实现的一个简单动画效果
Mar 30 Javascript
JavaScript 对象详细整理总结
Sep 29 Javascript
纯js实现html转pdf的简单实例(推荐)
Feb 16 Javascript
JS实现定时任务每隔N秒请求后台setInterval定时和ajax请求问题
Oct 15 Javascript
jQuery实现table表格checkbox全选的方法分析
Jul 04 jQuery
Vue js 的生命周期(看了就懂)(推荐)
Mar 29 Javascript
turn.js异步加载实现翻书效果
Jul 25 Javascript
从零撸一个pc端vue的ui组件库( 计数器组件 )
Aug 08 Javascript
解决vue移动端适配问题
Dec 12 #Javascript
js中位运算的运用实例分析
Dec 11 #Javascript
js中的数组对象排序分析
Dec 11 #Javascript
详解Vue源码之数据的代理访问
Dec 11 #Javascript
浅谈Vue 性能优化之深挖数组
Dec 11 #Javascript
vue 内置过滤器的使用总结(附加自定义过滤器)
Dec 11 #Javascript
Vue入门之数量加减运算操作示例
Dec 11 #Javascript
You might like
PHP 判断常量,变量和函数是否存在
2009/04/26 PHP
Php中用PDO查询Mysql来避免SQL注入风险的方法
2013/04/25 PHP
PHP执行linux命令常用函数汇总
2016/02/02 PHP
Yii实现文章列表置顶功能示例
2016/10/18 PHP
PHP实现的各类hash算法长度及性能测试实例
2017/08/27 PHP
swoole和websocket简单聊天室开发
2017/11/18 PHP
基于NodeJS的前后端分离的思考与实践(一)全栈式开发
2014/09/26 NodeJs
DOM基础教程之使用DOM控制表格
2015/01/20 Javascript
jquery实现带缩略图的可定制高度画廊效果(5种)
2015/08/28 Javascript
BootStrap Validator 版本差异问题导致的submitHandler失效问题的解决方法
2016/12/01 Javascript
jQuery实现动态文字搜索功能
2017/01/05 Javascript
Vue0.1的过滤代码如何添加到Vue2.0直接使用
2017/08/23 Javascript
Vue-cli3.X使用px2 rem遇到的问题及解决方法
2019/08/08 Javascript
vue双向绑定数据限制长度的方法
2019/11/04 Javascript
vue+element导航栏高亮显示的解决方式
2019/11/12 Javascript
JavaScript 自定义html元素鼠标右键菜单功能
2019/12/02 Javascript
jQuery操作事件完整实例分析
2020/01/10 jQuery
如何在vue中使用kindeditor富文本编辑器
2020/12/19 Vue.js
[39:08]完美世界DOTA2联赛PWL S3 LBZS vs CPG 第一场 12.12
2020/12/16 DOTA
跟老齐学Python之玩转字符串(2)
2014/09/14 Python
在类Unix系统上开始Python3编程入门
2015/08/20 Python
基于Python实现对PDF文件的OCR识别
2016/08/05 Python
Python插件virtualenv搭建虚拟环境
2017/11/20 Python
有趣的python小程序分享
2017/12/05 Python
pandas 实现将重复表格去重,并重新转换为表格的方法
2018/04/18 Python
matplotlib subplots 调整子图间矩的实例
2018/05/25 Python
对python 数据处理中的LabelEncoder 和 OneHotEncoder详解
2018/07/11 Python
python redis连接 有序集合去重的代码
2019/08/04 Python
python2和python3实现在图片上加汉字的方法
2019/08/22 Python
python 中Arduino串口传输数据到电脑并保存至excel表格
2019/10/14 Python
python实现对变位词的判断方法
2020/04/05 Python
Django权限设置及验证方式
2020/05/13 Python
大学毕业生通用自荐信范文
2013/10/31 职场文书
怎样写演讲稿
2014/01/04 职场文书
大学生撤销处分思想汇报
2014/09/12 职场文书
MySQL EXPLAIN输出列的详细解释
2021/05/12 MySQL