Express session應用與原理源碼解析


  • 什么是session
  • Express session實例應用
  • Express session源碼解析

 一、什么是session

1. 由於HTTP協議是無狀態的協議,所以服務端需要記錄用戶的狀態時,就需要用某種機制來識具體的用戶,這個機制就是Session.典型的場景比如購物車,當你點擊下單按鈕時,由於HTTP協議無狀態,所以並不知道是哪個用戶操作的,所以服務端要為特定的用戶創建了特定的Session,用用於標識這個用戶,並且跟蹤用戶,這樣才知道購物車里面有幾本書。這個Session是保存在服務端的,有一個唯一標識。在服務端保存Session的方法很多,內存、數據庫、文件都有。集群的時候也要考慮Session的轉移,在大型的網站,一般會有專門的Session服務器集群,用來保存用戶會話,這個時候 Session 信息都是放在內存的,使用一些緩存服務比如Memcached之類的來放 Session。
2. 思考一下服務端如何識別特定的客戶?這個時候Cookie就登場了。每次HTTP請求的時候,客戶端都會發送相應的Cookie信息到服務端。實際上大多數的應用都是用 Cookie 來實現Session跟蹤的,第一次創建Session的時候,服務端會在HTTP協議中告訴客戶端,需要在 Cookie 里面記錄一個Session ID,以后每次請求把這個會話ID發送到服務器,我就知道你是誰了。有人問,如果客戶端的瀏覽器禁用了 Cookie 怎么辦?一般這種情況下,會使用一種叫做URL重寫的技術來進行會話跟蹤,即每次HTTP交互,URL后面都會被附加上一個諸如 sid=xxxxx 這樣的參數,服務端據此來識別用戶。(url重寫可以參考: https://www.cnblogs.com/ttjava/p/3641014.html
Session是在服務端保存的一個數據結構,用來跟蹤用戶的狀態,這個數據可以保存在集群、數據庫、文件中;
(以上內容來源:https://www.zhihu.com/question/19786827/answer/28752144)

 二、Express session實例應用(登入驗證)

 1.構建項目結構
npm init -y
npm install express -save-dev
npm install cookie-parser -save-dev
npm install express-session -save-dev
npm install body-parser -save-dev
npm install ejs -save-dev

//項目結構
express_session
    page
        login.html
        home.html
    index.js
    node_modules
    package.json
    package-lock.json

這個實例主要解析node后台的express-session的應用,就不采用前端的數據渲染框架,而是采用后端模板渲染框架ejs。ejs官方文檔:https://ejs.bootcss.com/

 1 <!doctype html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>登入頁面</title>
 6 </head>
 7 <body>
 8 <form action="/login" method="POST">
 9     賬號:<input type="text" name="userid" />
10     密碼:<input type="password" name="userpassword"/>
11     <input type="submit" value="登入">
12 </form>
13 </body>
14 </html>
login.html
 1 <!doctype html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>首頁</title>
 6 </head>
 7 <body>
 8     <p id="use">用戶:<%= username %> | 賬號:<%= userid %></p>
 9     <p><a href="/logout">退出</a></p>
10 </body>
11 </html>
home.html
 1 //后台核心代碼
 2 const express = require('express');
 3 const cookieParser = require('cookie-parser');
 4 const session = require('express-session');
 5 const bodyParser = require('body-parser');
 6 const app = express();
 7 
 8 app.use(cookieParser());
 9 app.use(session({
10     cookie:{maxAge:1000*30},
11     secret:'leo'
12 }));
13 
14 app.set("view engine","html");//設置解析魔棒的文件類型
15 app.set("views",  __dirname+ "\\page");//設置模板路徑
16 app.engine('html',require('ejs').renderFile);//指定ejs引擎解析渲染模板路徑下的html文件
17 
18 app.use(bodyParser.json());
19 app.use(bodyParser.urlencoded({extended: true}));
20 
21 
22 //獲取登入頁面
23 app.get('/login',function(req,res){
24     res.sendFile(__dirname + '/page/login.html');
25 });
26 
27 //用戶登入(登入賬號驗證)
28 app.post('/login',function(req,res){
29     if(req.body.userid === '12300001111' && req.body.userpassword === '123456'){
30         req.session.userid = req.body.userid; //登入成功,設置session
31         req.session.username = '他鄉踏雪';     //...
32         res.redirect('/home');
33     }else{
34         res.json({ret_code:1,ret_msg:'賬號密碼錯誤'});
35     }
36 });
37 
38 //獲取主頁(響應首頁前通過session驗證用戶是否登入)
39 app.get('/home',function(req,res){
40     if(req.session.userid){
41         res.render('home',{
42             username:req.session.username,
43             userid:req.session.userid
44         });
45     }else{
46         res.redirect('/login');
47     }
48 });
49 
50 //退出
51 app.get('/logout',function(req,res){
52     req.session.username = null;
53     req.session.userid = null;
54    res.redirect('/login');
55 });
56 
57 app.listen(12306);

 三、Express session原理及源碼解析

 3.1基於cookie的session:

 

 

從某種意義上來說,session就是服務端的cookie,而且session是基於cookie的,就會受到瀏覽器的用戶禁用cookie的限制,在IE8時期可以通過HTML5的storage來填補這一空缺,因為在即便是瀏覽器禁用了cookie也僅僅只是不能在本地存儲cookie,服務的session如果根據IP和一系列數據簽名匹配到相關session,然后響應頭還是會攜帶cookie,所以就可以通過js解析cookie然后在本地使用storage來替代cookie,這是本地禁用cookie的解決方案。

同樣在服務端由於session默認存儲再內存中,如果服務停止或重啟內存的數據就會被清除,所以再服務端也是有必要對session做持久化的,這些在session上針對不同的session都由豐富的插件模塊,下面這份代碼是在第一部分基礎上實現了session文本存儲持久化,使用的是:session-file-store(官方文檔:https://www.npmjs.com/package/session-file-store),詳細見代碼。

 1 const express = require('express');
 2 const cookieParser = require('cookie-parser');
 3 const session = require('express-session');
 4 const bodyParser = require('body-parser');
 5 //session-file-store官方文檔:https://www.npmjs.com/package/session-file-store
 6 //express-session官方文檔(更多session存儲模式可以參考這個):https://github.com/expressjs/session
 7 const FileStore = require('session-file-store')(session);//引入session本地文件存儲模塊
 8 const fileStoreOptions = {};//配置session本地存儲模塊的相關參數,空對象表示默認參數,詳細參考
 9 const app = express();
10 
11 
12 
13 app.use(cookieParser());
14 app.use(session({
15     store: new FileStore(fileStoreOptions),//啟動session本地文件存儲
16     cookie:{maxAge:1000*30},
17     secret:'leo'
18 }));
19 
20 app.set("view engine","html");//設置解析魔棒的文件類型
21 app.set("views",  __dirname+ "\\page");//設置模板路徑
22 app.engine('html',require('ejs').renderFile);//指定ejs引擎解析渲染模板路徑下的html文件
23 
24 app.use(bodyParser.json());
25 app.use(bodyParser.urlencoded({extended: true}));
26 
27 
28 //獲取登入頁面
29 app.get('/login',function(req,res){
30     res.sendFile(__dirname + '/page/login.html');
31 });
32 
33 //用戶登入(登入賬號驗證)
34 app.post('/login',function(req,res){
35     if(req.body.userid === '12300001111' && req.body.userpassword === '123456'){
36         req.session.userid = req.body.userid; //登入成功,設置session
37         req.session.username = '他鄉踏雪';     //...
38         res.redirect('/home');
39     }else{
40         res.json({ret_code:1,ret_msg:'賬號密碼錯誤'});
41     }
42 });
43 
44 //獲取主頁(響應首頁前通過session驗證用戶是否登入)
45 app.get('/home',function(req,res){
46     if(req.session.userid){
47         res.render('home',{
48             username:req.session.username,
49             userid:req.session.userid
50         });
51     }else{
52         res.redirect('/login');
53     }
54 });
55 
56 //退出
57 app.get('/logout',function(req,res){
58     req.session.username = null;
59     req.session.userid = null;
60     res.redirect('/login');
61 });
62 
63 app.listen(12306);
View Code

更多session持久化可以參考session的官方文檔:https://github.com/expressjs/session,比較常見的MongoDB、Redis。

 2.session源碼淺析:

這一部分主要參考這篇博客:https://blog.csdn.net/weixin_33824363/article/details/91393870

session源碼只有四個模塊,分別是:cookie.js、memory.js、session.js、store.js再加一個入口模塊index.js。

cookie:用來配置cookie相關的參數。

store:用來實現session數據持久化操作的模塊。

session:主程序模塊。

memory:用來實現數據緩存,也就是session默認情況下存儲在內存中的操作。

index:入口模塊。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM