1. 程式人生 > >express-session

express-session

express-session 解析

session 是什麼

  • (注意這裡說的都是網站相關技術環境下。)
  • session 是一種標識對話的技術說法。通過 session ,我們能快速識別使用者的資訊,針對使用者提供不一樣的資訊。
  • session 的技術實現上:會對一次對話產生一個唯一的標識進行標識。

session 生命週期

session 標識產生的時機和清除時機:

  • 使用者已經登入:這個唯一標識會在使用者登入時產生,使用者點選退出時或者關閉瀏覽器時清除。
  • 使用者未登入: 這個唯一標識會在使用者進入網站時產生,使用者關閉所有網站相關頁面時清除。

session 生命週期: 在生成和清除之間,在網站內的頁面任意跳轉,session 標識不會發生變化。從 session 開始到清除,我們叫一次會話,也就是生成 session。

session 特點

  • 每次對話, session 的 id 是不一樣的。
  • session id 需要每次請求都由客戶端帶過來,用來標識本次會話。這樣就要求客戶端有能用儲存的 sesssionId。

session 技術方案

當前業界通用的方案是:cookie 。當然還有無 cookie 的方案,對每個連結都加上 sessionId 引數。

session 使用流程

  1. 使用者登入後,將 sessionId 存到 cookie 中。
  2. 使用者在請求的網站別的服務時,由瀏覽器請求帶上 cookie,傳送到伺服器。
  3. 伺服器拿到 sessionId 後,通過該 Id 找到儲存到在伺服器的使用者資訊。
  4. 然後再跟據使用者資訊,進行相應的處理。

從流程有幾個點要關注:

  1. 什麼時候根據 sessionId 去拿 session
  2. 確保 session 可用性

結合 express-session 來講講具體 session 的實現。

express-session 的分析

主要關注問題:

  • 怎樣產生 session
  • 怎樣去拿到 session
  • 怎樣去儲存 session
  • 怎樣去清除 session

express-session 位置

  1. express-session位置

express-session 有四個部分:

  1. request, response 與 session 的互動的部分
  2. session 資料結構
  3. session 中資料儲存的介面 store
  4. store 預設實現 memory(cookie 實現已被廢)
    在這裡插入圖片描述

不做中間層,直接使用進行處理,只用 express-session 進行處理資料。

const config = global.config;
const session = require('express-session');

/**
 * 該中介軟體主要把 express-session 和 client-session 集中起來處理,如果 memcached 出錯了,使用 cookie session
 * @param backSession cookeSession 的鍵名
 * @returns {function(*=, *=, *)}
 */
module.exports = (backSession) => {
    return (req, res, next) => {
        let notUseMemcached = _.get(req.app.locals.pc, 'session.removeMemcached', false);

        if (req.session && !notUseMemcached) {  // memcached 可用
            req.memcachedSessionError = false;
        } else {  // memcached 不可用
            // 重建 session
            res.emit('sessionError');
            req.memcachedSessionError = true;
            req.session = new session.Session(req);
            req.session.cookie = new session.Cookie({
                domain: config.cookieDomain,
                httpOnly: false
            });

            req.session = Object.assign(req.session, req[backSession].sessionBack);
        }

        Object.defineProperty(req.session, 'reset', {
            configurable: true,
            enumerable: false,
            value: function() {
                req.session.destory();
                req[backSession].reset();
            },
            writable: false
        });

        // 備份資料
        req[backSession].sessionBack = req.session;

        next();
    };
};