zoukankan      html  css  js  c++  java
  • 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:入口模块。

  • 相关阅读:
    asp.net套打
    如何使用哪个asp生成一个excel报表
    自定义打印纸张 c# gdi+ 精确位置打印 套打
    Java调用.dll文件
    [转载].NET实现之(套打解决方案(支持B/S和C/S))
    C#套打
    三十而立,从零开始学ios开发(一):准备起航
    DOTNETBAR的使用方法
    大型网站,要考虑的问题
    AppScan安全漏洞报告
  • 原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/13130336.html
Copyright © 2011-2022 走看看