🌐 Nodejs.cn

会话中间件

安装

🌐 Installation

这是一个可以通过npm注册表获取的Node.js模块。安装可以使用npm install命令完成:

🌐 This is a Node.js module available through the npm registry. Installation is done using the npm install command:

Terminal window
npm install express-session

Note

express-session 不包含其自身的 TypeScript 类型定义。如果你使用 TypeScript,还需要作为开发依赖从 DefinitelyTyped 安装社区维护的类型:

Terminal window
npm install --save-dev @types/express-session

API

var session = require('express-session');

session(options)

使用给定的 options 创建一个会话中间件。

🌐 Create a session middleware with the given options.

注意 会话数据 不会 保存在 cookie 本身中,只会保存会话 ID。会话数据存储在服务器端。

注意 自版本 1.5.0 起,cookie-parser 中间件 不再需要用于此模块的工作。此模块现在直接在 req/res 上读取和写入 cookie。如果此模块与 cookie-parser 之间的 secret 不相同,使用 cookie-parser 可能会导致问题。

警告 默认的服务器端会话存储 MemoryStore 是故意不为生产环境设计的。它在大多数情况下会泄漏内存,无法扩展到多个进程,并且仅用于调试和开发。

有关存储的列表,请参阅 兼容会话存储

🌐 For a list of stores, see compatible session stores.

选项

🌐 Options

express-session 在选项对象中接受这些属性。

会话 ID Cookie 的设置对象。默认值是 { path: '/', httpOnly: true, secure: false, maxAge: null }

🌐 Settings object for the session ID cookie. The default value is { path: '/', httpOnly: true, secure: false, maxAge: null }.

除了提供静态对象之外,你还可以传递回调函数来为每个请求动态生成 cookie 选项。回调函数接收 req 对象作为参数,并应返回一个包含 cookie 设置的对象。

🌐 In addition to providing a static object, you can also pass a callback function to dynamically generate the cookie options for each request. The callback receives the req object as its argument and should return an object containing the cookie settings.

var app = express();
app.use(
session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: function (req) {
var match = req.url.match(/^\/([^/]+)/);
return {
path: match ? '/' + match[1] : '/',
httpOnly: true,
secure: req.secure || false,
maxAge: 60000,
};
},
})
);

以下是可以在此对象中设置的选项。

🌐 The following are options that can be set in this object.

cookie.domain

指定 Domain Set-Cookie 属性的值。默认情况下,不设置任何域,大多数客户端会认为该 cookie 仅适用于当前域。

🌐 Specifies the value for the Domain Set-Cookie attribute. By default, no domain is set, and most clients will consider the cookie to apply to only the current domain.

cookie.expires

指定 Date 对象作为 ExpiresSet-Cookie 属性的值。默认情况下,不会设置过期时间,大多数客户端会将其视为“非持久性 Cookie”,并在诸如退出网页浏览器应用之类的条件下删除它。

🌐 Specifies the Date object to be the value for the Expires Set-Cookie attribute. By default, no expiration is set, and most clients will consider this a “non-persistent cookie” and will delete it on a condition like exiting a web browser application.

注意 如果选项中同时设置了 expiresmaxAge,则使用对象中最后定义的那个。

注意 不应直接设置 expires 选项;应只使用 maxAge 选项。

cookie.httpOnly

指定 HttpOnly Set-Cookie 属性的 boolean 值。当为真值时,设置 HttpOnly 属性,否则不设置。默认情况下,设置 HttpOnly 属性。

🌐 Specifies the boolean value for the HttpOnly Set-Cookie attribute. When truthy, the HttpOnly attribute is set, otherwise it is not. By default, the HttpOnly attribute is set.

注意 设置为 true 时要小心,因为符合规范的客户端将不允许客户端 JavaScript 查看 document.cookie 中的 cookie。

cookie.maxAge

指定在计算 Expires Set-Cookie 属性时使用的 number(以毫秒为单位)。这是通过获取当前服务器时间并将 maxAge 毫秒添加到该值来计算 Expires 日期时间来完成的。默认情况下,不设置最大年龄。

🌐 Specifies the number (in milliseconds) to use when calculating the Expires Set-Cookie attribute. This is done by taking the current server time and adding maxAge milliseconds to the value to calculate an Expires datetime. By default, no maximum age is set.

注意 如果选项中同时设置了 expiresmaxAge,则使用对象中最后定义的那个。

cookie.partitioned

指定 Partitioned Set-Cookie 属性的 boolean 值。当为真值时,Partitioned 属性会被设置,否则不会设置。默认情况下,Partitioned 属性未被设置。

🌐 Specifies the boolean value for the Partitioned Set-Cookie attribute. When truthy, the Partitioned attribute is set, otherwise it is not. By default, the Partitioned attribute is not set.

注意 这是一个尚未完全标准化的属性,将来可能会发生变化。这也意味着许多客户端可能会忽略此属性,直到他们理解它为止。

更多信息可以在提案中找到。

🌐 More information about can be found in the proposal.

cookie.path

指定 Path Set-Cookie 的值。默认情况下,此值设置为 '/',它是域的根路径。

🌐 Specifies the value for the Path Set-Cookie. By default, this is set to '/', which is the root path of the domain.

cookie.priority

指定 stringSet-Cookie Set-Cookie 属性 的值。

🌐 Specifies the string to be the value for the Priority Set-Cookie attribute.

  • 'low' 将把 Priority 属性设置为 Low
  • 'medium' 将把 Priority 属性设置为 Medium,这是未设置时的默认优先级。
  • 'high' 将把 Priority 属性设置为 High

有关不同优先级别的更多信息可以在规范中找到。

🌐 More information about the different priority levels can be found in the specification.

注意 这是一个尚未完全标准化的属性,将来可能会发生变化。这也意味着许多客户端在理解它之前可能会忽略此属性。

cookie.sameSite

指定 booleanstring 作为 SameSite Set-Cookie 属性的值。 默认情况下,这为 false

🌐 Specifies the boolean or string to be the value for the SameSite Set-Cookie attribute. By default, this is false.

  • true 将把 SameSite 属性设置为 Strict 以严格执行同站策略。
  • false 不会设置 SameSite 属性。
  • 'lax' 将把 SameSite 属性设置为 Lax 以实现宽松的同站点策略执行。
  • 'none' 将为显式跨站点 Cookie 将 SameSite 属性设置为 None
  • 'strict' 将把 SameSite 属性设置为 Strict 以严格执行同站策略。
  • 'auto' 将把 SameSite 属性设置为安全连接的 None,非安全连接的 Lax

有关不同执行级别的更多信息可以在 规范 中找到。

🌐 More information about the different enforcement levels can be found in the specification.

注意 这是一个尚未完全标准化的属性,未来可能会发生变化。这也意味着许多客户端在理解它之前可能会忽略此属性。

注意 有一个 草案规范 要求当 SameSite 属性被设置为 'none' 时,Secure 属性必须被设置为 true。一些网页浏览器或其他客户端可能正在采用该规范。

cookie.sameSite 选项也可以设置为特殊值 'auto',以使此设置自动匹配连接的安全性。当连接是安全的(HTTPS)时,SameSite 属性将被设置为 None 以启用跨站使用。当连接不安全(HTTP)时,SameSite 属性将被设置为 Lax,以在保持功能的同时提供更好的安全性。当 Express "trust proxy" 设置正确配置以简化开发与生产环境的配置时(特别是在 SAML 认证场景中),这非常有用。

🌐 The cookie.sameSite option can also be set to the special value 'auto' to have this setting automatically match the determined security of the connection. When the connection is secure (HTTPS), the SameSite attribute will be set to None to enable cross-site usage. When the connection is not secure (HTTP), the SameSite attribute will be set to Lax for better security while maintaining functionality. This is useful when the Express "trust proxy" setting is properly setup to simplify development vs production configuration, particularly for SAML authentication scenarios.

cookie.secure

指定 Secure Set-Cookie 属性的 boolean 值。当为真值时,Secure 属性被设置,否则不设置。默认情况下,Secure 属性未设置。

🌐 Specifies the boolean value for the Secure Set-Cookie attribute. When truthy, the Secure attribute is set, otherwise it is not. By default, the Secure attribute is not set.

注意 在将其设置为 true 时要小心,因为如果浏览器没有HTTPS连接,合规的客户端将不会在未来将cookie发送回服务器。

请注意,secure: true 是一个推荐选项。然而,它需要启用 HTTPS 的网站,即 HTTPS 对安全 cookie 是必需的。如果设置了 secure,并且通过 HTTP 访问你的网站,cookie 将不会被设置。如果你的 node.js 位于代理后,并且使用了 secure: true,则需要在 express 中设置 “trust proxy”:

🌐 Please note that secure: true is a recommended option. However, it requires an https-enabled website, i.e., HTTPS is necessary for secure cookies. If secure is set, and you access your site over HTTP, the cookie will not be set. If you have your node.js behind a proxy and are using secure: true, you need to set “trust proxy” in express:

var app = express();
app.set('trust proxy', 1); // trust first proxy
app.use(
session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: true },
})
);

在生产环境中使用安全 Cookie,同时允许在开发环境中进行测试,以下是一个基于 Express 中的 NODE_ENV 启用此设置的示例:

🌐 For using secure cookies in production, but allowing for testing in development, the following is an example of enabling this setup based on NODE_ENV in express:

var app = express();
var sess = {
secret: 'keyboard cat',
cookie: {},
};
if (app.get('env') === 'production') {
app.set('trust proxy', 1); // trust first proxy
sess.cookie.secure = true; // serve secure cookies
}
app.use(session(sess));

cookie.secure 选项也可以设置为特殊值 'auto',以便该设置自动匹配连接确定的安全性。如果网站同时提供 HTTP 和 HTTPS 访问,请在使用此设置时小心,因为一旦在 HTTPS 上设置了 cookie,它将在 HTTP 上不再可见。当 Express 的 "trust proxy" 设置正确配置以简化开发与生产环境的配置时,这非常有用。

🌐 The cookie.secure option can also be set to the special value 'auto' to have this setting automatically match the determined security of the connection. Be careful when using this setting if the site is available both as HTTP and HTTPS, as once the cookie is set on HTTPS, it will no longer be visible over HTTP. This is useful when the Express "trust proxy" setting is properly setup to simplify development vs production configuration.

genid

用于生成新会话 ID 的调用函数。提供一个返回字符串的函数,该字符串将用作会话 ID。如果在生成 ID 时想使用附加到 req 的某个值,该函数的第一个参数将传入 req

🌐 Function to call to generate a new session ID. Provide a function that returns a string that will be used as a session ID. The function is given req as the first argument if you want to use some value attached to req when generating the ID.

默认值是一个使用 uid-safe 库生成 ID 的函数。

🌐 The default value is a function which uses the uid-safe library to generate IDs.

注意 小心生成唯一的ID,以免你的会话发生冲突。

app.use(
session({
genid: function (req) {
return genuuid(); // use UUIDs for session IDs
},
secret: 'keyboard cat',
})
);
name

在响应中设置(并在请求中读取)的会话 ID Cookie 的名称。

🌐 The name of the session ID cookie to set in the response (and read from in the request).

默认值是 'connect.sid'

🌐 The default value is 'connect.sid'.

注意 如果你在同一个主机名上运行多个应用(这只是名称,即 localhost127.0.0.1;不同的方案和端口并不表示不同的主机名),那么你需要将会话 Cookie 彼此分开。最简单的方法就是为每个应用设置不同的 name

proxy

在设置安全 Cookie 时信任反向代理(通过 “X-Forwarded-Proto” 头)。

🌐 Trust the reverse proxy when setting secure cookies (via the “X-Forwarded-Proto” header).

默认值是 undefined

🌐 The default value is undefined.

  • true 将使用 “X-Forwarded-Proto” 头。
  • false 所有头信息都将被忽略,只有在存在直接的 TLS/SSL 连接时,连接才被视为安全。
  • undefined 使用 express 的 “trust proxy” 设置
resave

强制将会话保存回会话存储,即使在请求过程中会话从未被修改。根据你的存储方式,这可能是必要的,但它也可能导致竞争条件:当客户端向服务器发出两个并行请求时,一个请求中对会话的修改可能会在另一个请求结束时被覆盖,即使另一个请求没有做任何修改(这种行为也取决于你使用的存储)。

🌐 Forces the session to be saved back to the session store, even if the session was never modified during the request. Depending on your store this may be necessary, but it can also create race conditions where a client makes two parallel requests to your server and changes made to the session in one request may get overwritten when the other request ends, even if it made no changes (this behavior also depends on what store you’re using).

默认值是 true,但使用默认值已被弃用,因为默认值将来会更改。请研究此设置并选择适合你使用情况的值。通常,你会想要 false

🌐 The default value is true, but using the default has been deprecated, as the default will change in the future. Please research into this setting and choose what is appropriate to your use-case. Typically, you’ll want false.

我如何知道这对我的存储是否必要?最好的方法是向你的存储确认是否实现了 touch 方法。如果实现了,那么你可以安全地设置 resave: false。如果未实现 touch 方法,并且你的存储对存储的会话设置了过期日期,那么你很可能需要 resave: true

🌐 How do I know if this is necessary for my store? The best way to know is to check with your store if it implements the touch method. If it does, then you can safely set resave: false. If it does not implement the touch method and your store sets an expiration date on stored sessions, then you likely need resave: true.

rolling

强制在每个响应中设置会话标识符 cookie。过期时间将重置为原始的 maxAge,重新开始过期倒计时。

🌐 Force the session identifier cookie to be set on every response. The expiration is reset to the original maxAge, resetting the expiration countdown.

默认值是 false

🌐 The default value is false.

启用此功能后,会话标识符 cookie 将在自上次发送响应起maxAge过期,而不是在会话由服务器最后修改起maxAge过期。

🌐 With this enabled, the session identifier cookie will expire in maxAge since the last response was sent instead of in maxAge since the session was last modified by the server.

这通常与短的、非会话长度的 maxAge 值一起使用,以提供会话数据的快速超时,同时减少在进行中的服务器交互期间发生的可能性。

🌐 This is typically used in conjunction with short, non-session-length maxAge values to provide a quick timeout of the session data with reduced potential of it occurring during on going server interactions.

注意 当此选项设置为 truesaveUninitialized 选项设置为 false 时,cookie 将不会在未初始化会话的响应中设置。此选项仅在为请求加载了现有会话时修改行为。

saveUninitialized

强制将“未初始化”的会话保存到存储中。当会话是新的但未被修改时,它就是未初始化的。选择 false 对于实现登录会话、减少服务器存储使用或遵守法律要求在设置 cookie 前获得许可非常有用。选择 false 还可以帮助处理客户端在没有会话的情况下发出多个并行请求时的竞态条件。

🌐 Forces a session that is “uninitialized” to be saved to the store. A session is uninitialized when it is new but not modified. Choosing false is useful for implementing login sessions, reducing server storage usage, or complying with laws that require permission before setting a cookie. Choosing false will also help with race conditions where a client makes multiple parallel requests without a session.

默认值是 true,但使用默认值已被弃用,因为未来默认值将会改变。请研究此设置并选择适合你使用场景的值。

🌐 The default value is true, but using the default has been deprecated, as the default will change in the future. Please research into this setting and choose what is appropriate to your use-case.

注意 如果你在与 PassportJS 一起使用会话(Session),Passport 会在用户认证后向会话中添加一个空的 Passport 对象,这将被视为对会话的修改,从而导致会话被保存。此问题已在 PassportJS 0.3.0 中修复

secret

必填选项

这是用于对会话 ID Cookie 进行签名的密钥。该密钥可以是 Node.js crypto.createHmac 支持的任何类型的值(例如字符串或 Buffer)。它可以是单个密钥,也可以是多个密钥组成的数组。如果提供了密钥数组,则只有第一个元素会用于对会话 ID Cookie 进行签名,而在验证请求中的签名时会考虑所有元素。密钥本身不应容易被人解析,最好是随机字符组成。一种最佳实践可能包括:

🌐 This is the secret used to sign the session ID cookie. The secret can be any type of value that is supported by Node.js crypto.createHmac (like a string or a Buffer). This can be either a single secret, or an array of multiple secrets. If an array of secrets is provided, only the first element will be used to sign the session ID cookie, while all the elements will be considered when verifying the signature in requests. The secret itself should be not easily parsed by a human and would best be a random set of characters. A best practice may include:

  • 使用环境变量来存储秘密,确保秘密本身不会存在于你的代码库中。
  • 定期更新密钥,同时确保先前的密钥在数组中。

使用无法猜测的秘密将会把劫持会话的能力仅限于猜测会话 ID(由 genid 选项确定)。

🌐 Using a secret that cannot be guessed will reduce the ability to hijack a session to only guessing the session ID (as determined by the genid option).

更改密钥值将使所有现有会话失效。为了在不使会话失效的情况下轮换密钥,请提供一个密钥数组,将新的密钥作为数组的第一个元素,并将以前的密钥作为后续元素。

🌐 Changing the secret value will invalidate all existing sessions. In order to rotate the secret without invalidating sessions, provide an array of secrets, with the new secret as first element of the array, and including previous secrets as the later elements.

注意 HMAC-256 用于对会话 ID 进行签名。因此,密钥应至少包含 32 字节的熵。

store

会话存储实例,默认为新的 MemoryStore 实例。

🌐 The session store instance, defaults to a new MemoryStore instance.

unset

控制取消设置 req.session 的结果(通过 delete、设置为 null 等)。

🌐 Control the result of unsetting req.session (through delete, setting to null, etc.).

默认值是 'keep'

🌐 The default value is 'keep'.

  • 'destroy' 会话将在响应结束时被销毁(删除)。
  • 'keep' 存储中的会话将会被保留,但在请求过程中所做的修改将被忽略且不会保存。

req.session

要存储或访问会话数据,只需使用请求属性 req.session,该属性通常由存储序列化为 JSON,因此嵌套对象通常没有问题。例如,下面是一个用户特定的浏览计数器:

🌐 To store or access session data, simply use the request property req.session, which is (generally) serialized as JSON by the store, so nested objects are typically fine. For example below is a user-specific view counter:

// Use the session middleware
app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 } }));
// Access the session as req.session
app.get('/', function (req, res, next) {
if (req.session.views) {
req.session.views++;
res.setHeader('Content-Type', 'text/html');
res.write('<p>views: ' + req.session.views + '</p>');
res.write('<p>expires in: ' + req.session.cookie.maxAge / 1000 + 's</p>');
res.end();
} else {
req.session.views = 1;
res.end('welcome to the session demo. refresh!');
}
});

Session.regenerate(回调)

🌐 Session.regenerate(callback)

要重新生成会话,只需调用该方法。一旦完成,将在 req.session 初始化新的 SID 和 Session 实例,并且 callback 将被调用。

🌐 To regenerate the session simply invoke the method. Once complete, a new SID and Session instance will be initialized at req.session and the callback will be invoked.

req.session.regenerate(function (err) {
// will have a new session here
});

Session.destroy(回调)

🌐 Session.destroy(callback)

销毁会话并将取消设置 req.session 属性。一旦完成,将调用 callback

🌐 Destroys the session and will unset the req.session property. Once complete, the callback will be invoked.

req.session.destroy(function (err) {
// cannot access session here
});

Session.reload(回调)

🌐 Session.reload(callback)

从存储中重新加载会话数据并重新填充 req.session 对象。完成后,将调用 callback

🌐 Reloads the session data from the store and re-populates the req.session object. Once complete, the callback will be invoked.

req.session.reload(function (err) {
// session updated
});

Session.save(回调)

🌐 Session.save(callback)

将会话保存回存储,将存储中的内容替换为内存中的内容(尽管存储可能会执行其他操作——请参考存储的文档以了解具体行为)。

🌐 Save the session back to the store, replacing the contents on the store with the contents in memory (though a store may do something else—consult the store’s documentation for exact behavior).

如果会话数据已被修改,则在 HTTP 响应结束时会自动调用此方法(尽管可以在中间件构造函数中通过各种选项更改此行为)。因此,通常不需要调用此方法。

🌐 This method is automatically called at the end of the HTTP response if the session data has been altered (though this behavior can be altered with various options in the middleware constructor). Because of this, typically this method does not need to be called.

在某些情况下调用此方法是有用的,例如重定向、长时间运行的请求或在 WebSockets 中。

🌐 There are some cases where it is useful to call this method, for example, redirects, long-lived requests or in WebSockets.

req.session.save(function (err) {
// session saved
});

Session.touch()

更新 .maxAge 属性。通常不需要调用此方法,因为会话中间件会为你处理。

🌐 Updates the .maxAge property. Typically this is not necessary to call, as the session middleware does this for you.

req.session.id

每个会话都有一个与之关联的唯一 ID。此属性是 req.sessionID 的别名,无法修改。它已被添加以便可以从 session 对象访问会话 ID。

🌐 Each session has a unique ID associated with it. This property is an alias of req.sessionID and cannot be modified. It has been added to make the session ID accessible from the session object.

req.session.cookie

每个会话都有一个独特的 cookie 对象随之附带。这允许你对每个访客更改会话 cookie。例如,我们可以将 req.session.cookie.expires 设置为 false,以使 cookie 仅在用户代理的持续时间内保留。

🌐 Each session has a unique cookie object accompany it. This allows you to alter the session cookie per visitor. For example we can set req.session.cookie.expires to false to enable the cookie to remain for only the duration of the user-agent.

Cookie.maxAge

或者 req.session.cookie.maxAge 将返回剩余时间(以毫秒为单位),我们也可以重新分配一个新值来适当地调整 .expires 属性。以下内容基本上是等效的

🌐 Alternatively req.session.cookie.maxAge will return the time remaining in milliseconds, which we may also re-assign a new value to adjust the .expires property appropriately. The following are essentially equivalent

var hour = 3600000;
req.session.cookie.expires = new Date(Date.now() + hour);
req.session.cookie.maxAge = hour;

例如,当 maxAge 设置为 60000(一分钟)时,经过30秒,它将返回 30000,直到当前请求完成,此时将调用 req.session.touch() 来将 req.session.cookie.maxAge 重置为其原始值。

🌐 For example when maxAge is set to 60000 (one minute), and 30 seconds has elapsed it will return 30000 until the current request has completed, at which time req.session.touch() is called to reset req.session.cookie.maxAge to its original value.

req.session.cookie.maxAge; // => 30000

Cookie.originalMaxAge

req.session.cookie.originalMaxAge 属性返回会话 Cookie 的原始 maxAge(生存时间),以毫秒为单位。

🌐 The req.session.cookie.originalMaxAge property returns the original maxAge (time-to-live), in milliseconds, of the session cookie.

req.sessionID

要获取已加载会话的 ID,请访问请求属性 req.sessionID。这只是会话加载/创建时设置的只读值。

🌐 To get the ID of the loaded session, access the request property req.sessionID. This is simply a read-only value set when a session is loaded/created.

会话存储实现

🌐 Session Store Implementation

每个会话存储_必须_是一个EventEmitter并实现特定的方法。以下方法是必需的推荐的可选的列表。

🌐 Every session store must be an EventEmitter and implement specific methods. The following methods are the list of required, recommended, and optional.

  • 必需的方法是该模块将始终在存储上调用的方法。
  • 推荐的方法是如果可用,该模块将调用存储的方法。
  • 可选方法是该模块根本不会调用的方法,但有助于向用户呈现统一的存储。

有关示例实现,请查看 connect-redis 仓库。

🌐 For an example implementation view the connect-redis repo.

store.all(callback)

可选

这个可选方法用于将存储中的所有会话作为数组获取。callback 应该被调用为 callback(error, sessions)

🌐 This optional method is used to get all sessions in the store as an array. The callback should be called as callback(error, sessions).

store.destroy(sid, 回调)

🌐 store.destroy(sid, callback)

必填

此必需方法用于根据会话 ID(sid)从存储中销毁/删除会话。会话销毁后,应将 callback 调用为 callback(error)

🌐 This required method is used to destroy/delete a session from the store given a session ID (sid). The callback should be called as callback(error) once the session is destroyed.

store.clear(callback)

可选

此可选方法用于从存储中删除所有会话。一旦存储被清除,callback 应作为 callback(error) 调用。

🌐 This optional method is used to delete all sessions from the store. The callback should be called as callback(error) once the store is cleared.

store.length(callback)

可选

此可选方法用于获取存储中所有会话的数量。 callback 应该被调用为 callback(error, len)

🌐 This optional method is used to get the count of all sessions in the store. The callback should be called as callback(error, len).

store.get(sid, 回调)

🌐 store.get(sid, callback)

必填

此必需方法用于从存储中根据会话ID(sid)获取会话。callback 应该被作为 callback(error, session) 调用。

🌐 This required method is used to get a session from the store given a session ID (sid). The callback should be called as callback(error, session).

session 参数如果找到应该是一个会话,否则如果未找到会话(并且没有错误)则应是 nullundefined。当 error.code === 'ENOENT' 时,一个特殊情况被制定,以表现得像 callback(null, null)

🌐 The session argument should be a session if found, otherwise null or undefined if the session was not found (and there was no error). A special case is made when error.code === 'ENOENT' to act like callback(null, null).

store.set(sid, session, callback)

必填

此必需的方法用于根据会话 ID(sid)和会话(session)对象将会话插入或更新到存储中。一旦会话已设置到存储中,应将回调作为 callback(error) 调用。

🌐 This required method is used to upsert a session into the store given a session ID (sid) and session (session) object. The callback should be called as callback(error) once the session has been set in the store.

store.touch(sid, session, callback)

推荐

此推荐方法用于根据给定的会话 ID(sid)和会话(session)对象“触摸”指定的会话。一旦会话已被触碰,应将 callback 调用为 callback(error)

🌐 This recommended method is used to “touch” a given session given a session ID (sid) and session (session) object. The callback should be called as callback(error) once the session has been touched.

这主要在存储会自动删除空闲会话时使用,并且此方法用于向存储表示给定会话是活跃的,可能会重置空闲计时器。

🌐 This is primarily used when the store will automatically delete idle sessions and this method is used to signal to the store the given session is active, potentially resetting the idle timer.

兼容会话存储

🌐 Compatible Session Stores

以下模块实现了与此模块兼容的会话存储。请提交 PR 以添加其他模块 :)

🌐 The following modules implement a session store that is compatible with this module. Please make a PR to add additional modules :)

![★][aerospike-session-store-image] aerospike-session-store 使用 Aerospike 的会话存储。

![★][better-sqlite3-session-store-image] better-sqlite3-session-store 基于 better-sqlite3 的会话存储。

![★][cassandra-store-image] cassandra-store 基于 Apache Cassandra 的会话存储。

![★][cluster-store-image] cluster-store 一个用于在进程内/嵌入式存储(例如通过 knex 的 SQLite、leveldb、文件或内存)中使用的封装器,可与节点集群一起使用(适用于 Raspberry Pi 2 和其他多核嵌入式设备)。

![★][connect-arango-image] connect-arango 一个基于 ArangoDB 的会话存储。

![★][connect-azuretables-image] connect-azuretables 一个基于 Azure 表存储 的会话存储。

![★][connect-cloudant-store-image] connect-cloudant-store 一个基于 IBM Cloudant 的会话存储。

![★][connect-cosmosdb-image] connect-cosmosdb 一个基于 Azure Cosmos DB 的会话存储。

![★][connect-couchbase-image] connect-couchbase 一个基于 couchbase 的会话存储。

![★][connect-datacache-image] connect-datacache 基于 IBM Bluemix Data Cache 的会话存储。

![★][@google-cloud/connect-datastore-image] @google-cloud/connect-datastore 一个基于 Google Cloud Datastore 的会话存储。

![★][connect-db2-image] connect-db2 一个基于 IBM DB2 的会话存储,使用 ibm_db 模块构建。

![★][connect-dynamodb-image] connect-dynamodb 基于 DynamoDB 的会话存储。

![★][@google-cloud/connect-firestore-image] @google-cloud/connect-firestore 一个基于 Google Cloud Firestore 的会话存储。

![★][connect-hazelcast-image] connect-hazelcast Connect 和 Express 的 Hazelcast 会话存储。

![★][connect-loki-image] connect-loki 基于 Loki.js 的会话存储。

![★][connect-lowdb-image] connect-lowdb 基于 lowdb 的会话存储。

![★][connect-memcached-image] connect-memcached 基于 memcached 的会话存储。

![★][connect-memjs-image] connect-memjs 一个基于 memcached 的会话存储,使用 memjs 作为 memcached 客户端。

![★][connect-ml-image] connect-ml 一个基于 MarkLogic 服务器的会话存储。

![★][connect-monetdb-image] connect-monetdb 基于 MonetDB 的会话存储。

![★][connect-mongo-image] connect-mongo 基于 MongoDB 的会话存储。

![★][connect-mongodb-session-image] connect-mongodb-session 由 MongoDB 构建和维护的轻量级基于 MongoDB 的会话存储。

![★][connect-mssql-v2-image] connect-mssql-v2 一个基于 connect-mssql 的 Microsoft SQL Server 会话存储。

![★][connect-neo4j-image] connect-neo4j 一个基于 Neo4j 的会话存储。

![★][connect-ottoman-image] connect-ottoman 一个基于 couchbase ottoman 的会话存储。

![★][connect-pg-simple-image] connect-pg-simple 基于 PostgreSQL 的会话存储。

![★][connect-redis-image] connect-redis 基于 Redis 的会话存储。

![★][connect-session-firebase-image] connect-session-firebase 一个基于 Firebase 实时数据库 的会话存储

![★][connect-session-knex-image] connect-session-knex 一个会话存储,使用 Knex.js,它是一个适用于 PostgreSQL、MySQL、MariaDB、SQLite3 和 Oracle 的 SQL 查询构建器。

![★][connect-session-sequelize-image] connect-session-sequelize 一个使用 Sequelize.js 的会话存储,Sequelize.js 是一个用于 PostgreSQL、MySQL、SQLite 和 MSSQL 的 Node.js / io.js ORM。

![★][connect-sqlite3-image] connect-sqlite3 一个 SQLite3 会话存储,模仿 TJ 的 connect-redis 存储模式。

![★][connect-typeorm-image] connect-typeorm 一个基于 TypeORM 的会话存储。

![★][couchdb-expression-image] couchdb-expression 一个基于 CouchDB 的会话存储。

![★][dynamodb-store-image] dynamodb-store 基于 DynamoDB 的会话存储。

![★][express-etcd-image] express-etcd 一个基于 etcd 的会话存储。

![★][express-mysql-session-image] express-mysql-session 使用 node-mysql 模块通过原生 MySQL 的会话存储。

![★][express-nedb-session-image] express-nedb-session 一个基于 NeDB 的会话存储。

![★][express-oracle-session-image] express-oracle-session 一个使用本地 oracle 通过 node-oracledb 模块的会话存储。

![★][express-session-cache-manager-image] express-session-cache-manager 一个实现了 cache-manager 的存储,支持多种存储类型

![★][express-session-etcd3-image] express-session-etcd3 一个基于 etcd3 的会话存储。

![★][express-session-level-image] express-session-level 一个基于 LevelDB 的会话存储。

![★][express-session-rsdb-image] express-session-rsdb 基于 Rocket-Store 的会话存储:一个非常简单、超快速且功能强大的扁平文件数据库。

![★][express-sessions-image] express-sessions 一个支持 MongoDB 和 Redis 的会话存储。

![★][firestore-store-image] firestore-store 一个基于 Firestore 的会话存储。

基于会话的存储。支持 Fortune 支持的所有后端(MongoDB、Redis、Postgres、NeDB)。

🌐 based session store. Supports all backends supported by Fortune (MongoDB, Redis, Postgres, NeDB).

![★][hazelcast-store-image] hazelcast-store 一个基于 Hazelcast Node Client 构建的 Hazelcast 会话存储。

![★][level-session-store-image] level-session-store 基于 LevelDB 的会话存储。

![★][lowdb-session-store-image] lowdb-session-store 一个基于 lowdb 的会话存储。

![★][medea-session-store-image] medea-session-store 一个基于Medea的会话存储。

![★][memorystore-image] memorystore 一个为生产环境打造的内存会话存储。

![★][mssql-session-store-image] mssql-session-store 基于 SQL Server 的会话存储。

![★][nedb-session-store-image] nedb-session-store 一个基于 NeDB 的替代会话存储(可以是内存或文件持久化)。

![★][@quixo3/prisma-session-store-image] @quixo3/prisma-session-store 一个用于 Prisma 框架 的会话存储。

![★][restsession-image] restsession 使用 RESTful API 存储会话

![★][sequelstore-connect-image] sequelstore-connect 一个使用 Sequelize.js 的会话存储。

![★][session-file-store-image] session-file-store 基于文件系统的会话存储。

![★][session-pouchdb-store-image] session-pouchdb-store PouchDB / CouchDB 的会话存储。接受嵌入的、自定义的或远程的 PouchDB 实例,并支持实时同步。

![★][@databunker/session-store-image] @databunker/session-store 一个基于 Databunker 的加密会话存储。

![★][sessionstore-image] sessionstore 一个可以与各种数据库协作的会话存储。

![★][tch-nedb-session-image] tch-nedb-session 一个基于 NeDB 的文件系统会话存储。

例子

🌐 Examples

查看计数器

🌐 View counter

一个简单的例子,使用 express-session 来存储用户的页面浏览量。

🌐 A simple example using express-session to store page views for a user.

var express = require('express');
var parseurl = require('parseurl');
var session = require('express-session');
var app = express();
app.use(
session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
})
);
app.use(function (req, res, next) {
if (!req.session.views) {
req.session.views = {};
}
// get the url pathname
var pathname = parseurl(req).pathname;
// count the views
req.session.views[pathname] = (req.session.views[pathname] || 0) + 1;
next();
});
app.get('/foo', function (req, res, next) {
res.send('you viewed this page ' + req.session.views['/foo'] + ' times');
});
app.get('/bar', function (req, res, next) {
res.send('you viewed this page ' + req.session.views['/bar'] + ' times');
});
app.listen(3000);

用户登录

🌐 User login

一个使用 express-session 将用户保持登录状态在会话中的简单示例。

🌐 A simple example using express-session to keep a user log in session.

var escapeHtml = require('escape-html');
var express = require('express');
var session = require('express-session');
var app = express();
app.use(
session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
})
);
// middleware to test if authenticated
function isAuthenticated(req, res, next) {
if (req.session.user) next();
else next('route');
}
app.get('/', isAuthenticated, function (req, res) {
// this is only called when there is an authentication user due to isAuthenticated
res.send('hello, ' + escapeHtml(req.session.user) + '!' + ' <a href="/logout">Logout</a>');
});
app.get('/', function (req, res) {
res.send(
'<form action="/login" method="post">' +
'Username: <input name="user"><br />' +
'Password: <input name="pass" type="password"><br />' +
'<input type="submit" text="Login"></form>'
);
});
app.post('/login', express.urlencoded({ extended: false }), function (req, res) {
// login logic to validate req.body.user and req.body.pass
// would be implemented here. for this example any combo works
// regenerate the session, which is good practice to help
// guard against forms of session fixation
req.session.regenerate(function (err) {
if (err) next(err);
// store user information in session, typically a user id
req.session.user = req.body.user;
// save the session before redirection to ensure page
// load does not happen before session is saved
req.session.save(function (err) {
if (err) return next(err);
res.redirect('/');
});
});
});
app.get('/logout', function (req, res, next) {
// logout logic
// clear the user from the session object and save.
// this will ensure that re-using the old session id
// does not have a logged in user
req.session.user = null;
req.session.save(function (err) {
if (err) next(err);
// regenerate the session, which is good practice to help
// guard against forms of session fixation
req.session.regenerate(function (err) {
if (err) next(err);
res.redirect('/');
});
});
});
app.listen(3000);

调试

🌐 Debugging

该模块在内部使用 debug 模块来记录有关会话操作的信息。

🌐 This module uses the debug module internally to log information about session operations.

要查看所有内部日志,在启动应用时将 DEBUG 环境变量设置为 express-session(在此示例中为 npm start):

🌐 To see all the internal logs, set the DEBUG environment variable to express-session when launching your app (npm start, in this example):

Terminal window
$ DEBUG=express-session npm start

在 Windows 上,使用相应的命令;

🌐 On Windows, use the corresponding command;

Terminal window
> set DEBUG=express-session & npm start

许可证

🌐 License

MIT