Express session应用与原理源码解析
- 什么是session
- Express session实例应用
- Express session源码解析
一、什么是session
二、Express session实例应用(登入验证)
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>
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>
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);
更多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:入口模块。