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编写俄罗斯方块
Mar 30 Javascript
js改变embed标签src值的方法
Apr 10 Javascript
jQuery中animate动画第二次点击事件没反应
May 07 Javascript
实例讲解jquery中mouseleave和mouseout的区别
Feb 17 Javascript
基于jquery二维码生成插件qrcode
Jan 07 Javascript
浅谈node中的exports与module.exports的关系
Aug 01 Javascript
vue计算属性时v-for处理数组时遇到的一个bug问题
Jan 21 Javascript
Angular通过指令动态添加组件问题
Jul 09 Javascript
layui多图上传实现删除功能的例子
Sep 23 Javascript
vue 解决路由只变化参数页面组件不更新问题
Nov 05 Javascript
jQuery实现全选、反选和不选功能的方法详解
Dec 04 jQuery
JavaScript原型继承和原型链原理详解
Feb 04 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
使用网络地址转换实现多服务器负载均衡
2006/10/09 PHP
浅析php插件 Simple HTML DOM 用DOM方式处理HTML
2013/07/01 PHP
php中判断数组相等的方法以及数组运算符介绍
2015/03/30 PHP
php定期拉取数据对比方法实例
2019/09/22 PHP
javascript 动态添加事件代码
2008/11/30 Javascript
一段批量给页面上的控件赋值js
2010/06/19 Javascript
Javascript实现重力弹跳拖拽运动效果示例
2013/06/28 Javascript
javascript 弹出的窗口返回值给父窗口具体实现
2013/11/23 Javascript
浅析JavaScript中的CSS属性及命名规范
2013/11/28 Javascript
js实现文本框中焦点在最后位置
2014/03/04 Javascript
深入理解逻辑表达式的用法 与或非的用法
2016/06/06 Javascript
JavaScript提高网站性能优化的建议(二)
2016/07/24 Javascript
Vue header组件开发详解
2018/01/26 Javascript
jQuery+koa2实现简单的Ajax请求的示例
2018/03/06 jQuery
JS实现在线ps功能详解
2019/07/31 Javascript
javascript使用正则表达式实现注册登入校验
2020/09/23 Javascript
JavaScript实现HTML导航栏下拉菜单
2020/11/25 Javascript
使用python开发vim插件及心得分享
2014/11/04 Python
python中urllib模块用法实例详解
2014/11/19 Python
Python中线程的MQ消息队列实现以及消息队列的优点解析
2016/06/29 Python
Python实现的连接mssql数据库操作示例
2018/08/17 Python
在PyCharm中三步完成PyPy解释器的配置的方法
2018/10/29 Python
解决Django中多条件查询的问题
2019/07/18 Python
keras自定义回调函数查看训练的loss和accuracy方式
2020/05/23 Python
python实点云分割k-means(sklearn)详解
2020/05/28 Python
泰国折扣酒店预订:Hotels2Thailand
2018/03/20 全球购物
教育学专业毕业生的自我鉴定
2013/11/26 职场文书
应届医学毕业生求职信分享
2013/12/02 职场文书
超市总经理岗位职责
2014/02/02 职场文书
机电一体化求职信
2014/03/10 职场文书
酒店管理求职信范文
2014/04/06 职场文书
群众路线学习心得体会范文
2014/11/05 职场文书
2015年学校党建工作总结
2015/05/19 职场文书
2016庆祝教师节新闻稿
2015/11/25 职场文书
CSS3 制作的悬停缩放特效
2021/04/13 HTML / CSS
JavaScript小技巧带你提升你的代码技能
2021/09/15 Javascript