Express.js 中的 Sessions 如何工作?(译)

世界上任何一个拥有用户数据的 web 应用都必须处理 sessions。作为一名开发者,我们必须要知道它们是什么以及如何处理它们。
在这篇文章中,我想要分享的是:

  • session 是什么?
  • session 如何存储数据?
  • 你如何决定存放 session 数据的位置?
  • 在 sessions 工作时,你必须意识到的安全性上的影响有哪些?
    在一些示例代码中,我将会运用 session npm module ,它很有可能是最常见的 session 库。

session 是什么?

session 是存储你通过请求获取到的数据的地方。每一个访问你网站的用户都有一个唯一的 session。当他们浏览你应用的时候,你就可以使用 session 去存储和获取用户数据。
session 对 web 应用开发来讲是必须有的,因为 session 允许应用去存储状态。基于用户在页面 A 上的一个动作,我们就可以展示出一个不同的页面 B。如果没有 session,应用将是无状态的,而且很无用。
这里展示了你如何使用 Express 去建立一个简单的 session

import express from 'express';
import session from 'express-session';
var app = express();
app.use(session());

如果你的应用已经有了可使用的 sessions, 你可以在一个路由处理中设置一些数据:

app.use(session({ secret: 'this-is-a-secret-token', cookie: { maxAge: 60000 }}));

// Access the session as req.session
app.get('/', function(req, res, next) {
  var sessData = req.session;
  sessData.someAttribute = "foo";
  res.send('Returning with some text');
});

在另一个路由处理中读到它:

app.get('/bar', function(req, res, next) {
  var someAttribute = req.session.someAttribute;
  res.send(`This will print the attribute I set earlier: ${someAttribute}`);
});

sessions 可以用不同的方式存储它们的信息。存储 session 数据最受欢迎的方式有:

  • 在应用内存中
  • 在 cookie 中
  • 在内存缓存中
  • 在数据库中

使用应用内存存储 session 数据

这是常见的最简单的存储方式,但在生产环境中不用。
用这种方式存储从根本上意味着数据在应用执行时间中的有效期内被存储,一旦你的 web 应用服务器宕机了或停止运行了,所有的 session 数据都会被移除。
在内存中存储 session 数据也会导致内存泄露。当你的应用保持运行的时候,越来越多的内存被占用,直到应用因为内存不足而退出。
为了开发的目的,把 session 数据存在内存中经常很有用。然而,这儿还有更好的存储 session 数据的方式。

使用 cookie 存储 session 数据

cookie 通常是从 web 服务器发送到你的 web 浏览器上的一小块数据。它允许服务器存储一个具体用户相关的信息。
cookies 的一种常见用法就是存储 session 数据,它的工作流程是:
1、服务器发送一个 cookie 给 web 浏览器,并且在客户端存储一段时间(称为 expiration time)。
2、当用户随后向 web 服务器发起一个请求时,这个 cookie 会和这个请求一起发送,服务器可以读到 cookie 中包含的信息。
3、如果需要的话,服务器可以修改 cookie,然后再把它返回给浏览器。
每次你发起一个请求,你的浏览器都会把 cookie 发送给服务器,直到 cookie 过期为止。
类似 express-session 这样的模块会给你提供一个友好的 API 和 sessions 一起工作(让你可以获取 & 设置 session 里的数据 ),但是在底层,它可以通过 cookie 保存和恢复这个数据。

sessions-1.png

Express-session 也提供一些方法来保证你 cookies 的安全性。我们在这不会讲述安全细节,但是我推荐你通过阅读文档来详细研究安全细则。这对于确保你应用里的 cookie 信息不被暴露是非常重要的。使用 cookie 存储 session 数据也带来了一些问题:
1、可以存储的数据量很小,大约只有 4kb。
2、因为每次发送请求都会携带 cookie,如果你在 cookie 中存储了一堆数据,它将会增加请求中的数据量,从而导致你的网站性能降低。
3、如果攻击者弄清楚了你的 cookies 是如何加密的,那么你的 cookies 就危险了。攻击者将能读到 cookies 中存储的信息,这可是用户敏感信息啊!

使用内存缓存存储 session 数据

内存缓存是可以存储一小堆键值数据的地方。使用内存缓存存储 session 信息的最出名的两个例子就是 RedisMemcached。在内存缓存中存储 session 数据的时候,服务器仍然使用 cookie,但是这个 cookie 只包含一个唯一的 sessionId。这个 sessionId 在服务器对储存库进行查找的时候使用。

sessions-2.png

使用内存缓存的时候,你的 cookie 只包含一个 session ID。它避免了私人用户信息被暴露在 cookie 中的危险。使用内存缓存存储 session 数据的优点:
1、基于键值对数据存储,便于查找。
2、它们和你的应用服务器分隔开来。这种分隔降低了依赖。
3、单独一个内存存储可以服务好多个应用。
4、通过移除老的 session 数据来自动管理内存。
当然,这种存储方式也有一些缺点:
1、它们是另一台服务器,需要进行建立和管理。
2、对一些小应用来说可能是杀鸡用了牛刀。一般这种情况的话,使用数据库存储或者 cookies 存储效果更好。
3、重置缓存的唯一办法就是移除所有存储在它里面的 sessions。
下面的示例告诉你如何来用 express-session 来建立一个类似 Memcached 的内存缓存,通过 connect-memcached 模块。

var express      = require('express');
var session      = require('express-session');
var cookieParser = require('cookie-parser');
var app          = express();
var MemcachedStore = require('connect-memcached')(session);
 
app.use(cookieParser());
app.use(session({
      secret  : 'some-private-key',
      key     : 'test',
      proxy   : 'true',
      store   : new MemcachedStore({
        hosts: ['127.0.0.1:11211'], //this should be where your Memcached server is running
        secret: 'memcached-secret-key' // Optionally use transparent encryption for memcache session data 
    })
}));

使用数据库存储 session 数据

最后,我们谈一下在传统的数据库中存储 session 数据,比如 MySQL 和 PostgreSQL。在大多数情况下,它以一种类似于在内存中存储 session 数据的方式来工作。session cookie 仍然只含有一个 sessionId。在这种情况下,它将会匹配数据库里的 session 表中的第一个 key 值。总的来讲,我不推荐使用数据库来存储 session 数据,我这么做的唯一的理由是它需要花费大量精力去建立 Memcached 或 Redis。从数据库中恢复数据比用内存缓存恢复要慢的多,因为数据存储在硬盘上,而不是内存中。当你把 session 数据存在数据库里的时候,你会被数据库暴击的。。。。另外,你必须自己全权管理老的 session 数据。如果你没有移除老的 session 数据,你的数据库将被成千上万条无用数据行占用。这里有许多数据库存储,你可以使用 express-session。在 README 中查看完整列表

你应该在哪存储你的 session 数据?

我们讨论了常用的三种方式存储来存储你的 session 数据。那么你应该在哪存储你的 session 数据呢?
总的来说,我遵循这个规则:“内存第一(译者注:这里应该是指内存缓存),cookie 第二,最后是数据库”。
如果你使用 Memcached 或 Redis,我会和你相伴。如果不是,把你的 session 数据存在 cookie,但一定要确保你私钥的安全。最后,你可以把你的 session 数据存在数据库里,但一定要有一个移除老 session 数据的计划。
原文地址:http://nodewebapps.com/2017/0...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容