美文网首页javaScritp程序员
nodejs--session&&cookie

nodejs--session&&cookie

作者: DragonRat | 来源:发表于2018-06-30 19:00 被阅读0次

    作者:烨竹

    cookie简介:

    cookie 是 http 协议的一部分,它的处理分为如下几步:
    服务器向客户端发送 cookie。
    通常使用 HTTP 协议规定的 set-cookie 头操作。
    规范规定 cookie 的格式为 name = value 格式,且必须包含这部分。
    浏览器将 cookie 保存。
    每次请求浏览器都会将 cookie 发向服务器。

    其他可选的 cookie 参数会影响将 cookie 发送给服务器端的过程,主要有以下几种:
    path:表示 cookie 影响到的路径,匹配该路径才发送这个 cookie。
    expires 和 maxAge:告诉浏览器这个 cookie 什么时候过期,expires 是 UTC 格式时间,maxAge 是 cookie 多久后过期的相对时间。当不设置这两个选项时,会产生 session cookie,session cookie 是 transient 的,当用户关闭浏览器时,就被清除。一般用来保存 session 的 session_id。
    secure:当 secure 值为 true 时,cookie 在 HTTP 中是无效,在 HTTPS 中才有效。
    httpOnly:浏览器不允许脚本操作 document.cookie 去更改 cookie。一般情况下都应该设置这个为 true,这样可以避免被 xss 攻击拿到 cookie。

    具体参考:
    http://expressjs.com/zh-tw/4x/api.html#res
    http://wiki.jikexueyuan.com/project/node-lessons/cookie-session.html
    https://blog.csdn.net/kuangshp128/article/details/75152458
    https://cnodejs.org/topic/5212d82d0a746c580b43d948

    Cookie在express上的应用

    首先,我们进入express的官网看到,它提供了几个cookie相关的API参考
    Response (server设定cookie,回传给client)
    res.cookie(name,value [,options])
    将cookie设置name为value。该value参数可能是一个字符串或对象转换为JSON。
    该options参数是一个可以具有以下属性的对象
    res.clearCookie(name [,options])清除指定的cookie
    Request (向client接收cookie)
    req.signedCookies
    取得由client端接收过来有设定签章的请求,让它形成未签章并加以使用。
    有加上签章的cookie,好处是,只有开发者自己知道的签章加上回应出去给个别oookie时,使用者根本不知道你开发者签了什么,要窜改也难。否则,恶意攻击容易放入req.cookie。

    ex.接收过来的Cookie: user= ladykaka .CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
    当后面这一串.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3签章与开发人员设定的签章有相应,req.signedCookies.user的值即为: ladykaka

    设定签章

    express设定签章,必须使用cookie-parser middleware,它的作用是即为cookie做一个签章。
    用法:在你的express物件,加入cookieParser(your sign)即可!
    参数your sign建议是一个128 bytes的随机字串。

    var app=express();
    app.use(cookieParser('123456789'));
    

    登陆功能:
    建立login文件夹,并且初始化

      mkdir login
        cd login
        npm init  
    

    初始化参数:
    package name:你这个Project要叫什么名字
    version:你决定这个Project现在该是第几版
    description: Project基本介绍
    entry point:进入点,如果要跑你的Project应该要执行哪个档案
    author:作者(自己)
    license:你这个Project是采用什么授权的
    test command:这个不太重要,待会会说明

    创建相关模块:

        npm install express --save
        npm install body-parser --save
        npm install cookie-parser --save
         npm install pug --save
    

    /public/cookie下建立好静态网页

    <form action="/cookie/post" method="post">
        First name:<input name="firstName" type="text"/><br>
        Last name:<input name="lastName" type="text"/><br>
        <input type="submit" />
    </form>
    

    view下建立pug样板

    //index.pug
    extends layout
    
    block content
      h1= title
      p hello #{member} 
       if logstatus == false
         a(href="Login.html") 登入
       else
         a(href="./logout") 登出
    
    //layout.pug
    doctype html
    html
      head
        title= title
        link(rel='stylesheet', href='/stylesheets/style.css')
      body
        block content
    
    //error.pug
    extends layout
    
    block content
      h1= message
      h2= error.status
      pre #{error.stack}
    

    建立express web server

    //載入第三方模組
    var express = require('express');
    var cookieParser = require('cookie-parser');
    var bodyParser = require('body-parser');
     
    //载入路由档案
    var routerCookie=require('./routes/loginAPI');
     
    var app = express(); //建立一个express物件
     
    //set view engine
    app.set("view engine","pug")
    //set view directory
    app.set("views",__dirname+"/views")
     
    //將request进來的data 转成 json()
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
     
    
    // Create a router to handle routes for a set of loginAPI
    // 抓出來, 变成独立档案
    // -------------------------------------------------------
     
    //静态档案 like .js, .json, .xml, html....
    app.use(express.static(__dirname+'/public'));
    
     
    // 允许 /cookie 使用這個路由
    app.use('/cookie', routerCookie);
     
    app.listen(3000,function(){
        console.log('Ready...for 3000,二哈!!!');
    });
    

    重头戏来了
    上方index.js下面的转json数据之后,加入一个签章:

    // sign for cookie
    app.use(cookieParser('123456789'));
    

    建立路由档案,新建routes文件夹,在下面添加loginAPI.js文件

    var express = require("express");
    var loginAPI =express.Router();
    //进入需要验证的界面
    loginAPI.get('/', function(req, res) {
            //一开始预设,所有的登入状态isLogin都是false,预设的登入者是guest。
            //如果,我们接收到的cookie皆存在,则改变登入者姓名及登入状态。
            //然而,无论有没有登入,皆会导到index.jade样版,去做呈现。
        var name='guest';
        isLogin=false;
        if(req.signedCookies.firstName && req.signedCookies.lastName){
            name=req.signedCookies.firstName+ ' '+req.signedCookies.lastName;
             isLogin = true;
             
      }
    
       res.render('index', { title: 'Express', member:name, logstatus:isLogin });
     }); 
    //如果表单送出后,只要fristName, lastName其中一个栏位没有填写,则再重回登入页
    //如果都有填了,则可以建立cookie,在/cookie之下有效,使用签章,cookie生存值100分钟。
    //建好以后,导向到/cookie即….进入需要验证的页面
    loginAPI.post('/post', function(req, res) {
        // ...
        if(req.body.firstName=="" || req.body.lastName=="")
        {
                 return res.redirect('Login.html');
        }else{
            res.cookie('firstName', req.body.firstName, { path: '/cookie', signed: true, maxAge:600000});  //set cookie
            res.cookie('lastName', req.body.lastName, { path: '/cookie', signed: true, maxAge:600000 }); //set cookie
            return res.redirect('/cookie');
        }
     });
     
    
        // 登出...
    loginAPI.get('/logout', function(req, res) {
        // ...登出清理cookie,并返回路由、cookie
            res.clearCookie('firstName',{path:'/cookie'});
            res.clearCookie('lastName',{path:'/cookie'});
            return res.redirect('/cookie');
    });
    
    module.exports = loginAPI;
    

    做完后
    目录结构如下图:

    访问效果如下:

    session

    session store 使用
    因为session是储存在server端的,所以,我们可以为Session设置存放位置。
    一般而言,session可以存放在:
    1.记忆体内存
    2.cookie本身
    3.redis或memcached等缓存中(常见)
    4.数据库中ex. mongoDB。

    这边,我将示范,在mongoDB 存session,很简单,只要3个步骤:

    1. 首先,必须先安装express-sessionconnect-mongo (还有更多session储存的API,可以参考 https://github.com/expressjs/session#compatible-session-stores))
    2. 安装好后,我们可以用简单的 计数器程式做例子!首先,引入module:
    var session = require('express-session');
    const MongoStore = require('connect-mongo')(session);
    

    引入后,在session相关option设置,加入
    store:new MongoStore({url:’mongodb://localhost:27017/sessiondb’})
    如图:


    如此,大功告成!!

    在robo 3T查看数据是否增加

    登陆
    建模:express, express-session, body-parser,connect-mongo这些
    在public下添加session文件夹,在添加login.html

    <form action="/session/post" method="post">
        First name:<input name="firstName" type="text"/><br>
        Last name:<input name="lastName" type="text"/><br>
        <input type="submit" />
    </form>
    

    index.js

    //載入第三方模組
    var express = require('express');
    
    
    // 引入 express-session
    var session = require('express-session');
    // session store
    const MongoStore = require('connect-mongo')(session);
    
    
    var bodyParser = require('body-parser');
    //载入路由档案
    var routerSession=require('./routes/loginAPI');
     
    var app = express(); //建立一个express物件
     
    //set view engine
    app.set("view engine","pug")
    //set view directory
    app.set("views",__dirname+"/views")
     
    //將request进來的data 转成 json()
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
     
    //設置session相關設定
    app.use(session({
        secret: 'recommand 128 bytes random string',
        store:new MongoStore({url:'mongodb://tester:password@localhost:27017/lxkdb'}),
        resave: false,
        saveUninitialized: true,
        cookie: { maxAge: 600 * 1000 } //10分鐘到期
       
      }));
    // Create a router to handle routes for a set of loginAPI
    // 抓出來, 变成独立档案
    // -------------------------------------------------------
     
    //静态档案 like .js, .json, .xml, html....
    app.use(express.static(__dirname+'/public'));
    
     
    // 允许 /session 使用這個路由
    app.use('/session', routerSession);
     
    app.listen(3000,function(){
        console.log('Ready...for 3000,二哈!!!');
    });
    

    loginAPI.js

    var express = require("express");
    var loginAPI =express.Router();
    //进入需要验证的界面
    var isLogin=false;
    
    loginAPI.get('/',function(req,res){
        // 一开始预设,所有的登入状态isLogin都是false,预设的登入者是guest。
    //如果,我们接收到的session皆存在,则改变登入者姓名及登入状态。
    //然而,无论有没有登入,皆会导到index.jade样版,去做呈现。
    //这边与cookie的不同,多了一個測試 進入次數的計數呈現(非必要)
        var name='guest';
        isLogin=false;
        var Logtime=1;
        if(req.session.firstName && req.session.lastName){
            name=req.session.firstName+ ' '+req.session.lastName;
            isLogin = true;
            Logtime= req.session.time;
        }
     
         res.render('index', { title: 'Express', member:name, logstatus:isLogin,time:Logtime });
    });
    
      
    
    loginAPI.post('/post', function(req, res) {
        // 表单送出后,开始进行条件判断。
    //如果fristName, lastName其中一个栏位没有填写,则再重回登入页。
    //否则,再进行下一个条件判断:只要,两者输入,在session store已有(在未登出情况下,同一笔连线),表示session早已存在,登入次数加1,直接到需要验证的页面即可!– 否则,重新设置session,并导向验证页面。(這裡的判別,可以做省略,主要是為了測試store用!)
        if(req.body.firstName=="" || req.body.lastName=="")
        {
            return res.redirect('Login.html');
        }else if(req.body.firstName==req.session.firstName
                 && req.body.lastName==req.session.lastName)
                   //如果輸入的,在session store已有儲存..
        {
             req.session.time++; //同一連線的登入次數, 就加 1
             return res.redirect('/session');    //就直接導向到...
        }
        else
        {
            //session store裡沒有的,就會重新設置
            req.session.firstName=req.body.firstName;
            req.session.lastName=req.body.lastName;
            req.session.time=1;
              return res.redirect('/session');
        }
     
    });
     
    
        // 登出...
        loginAPI.get('/logout', function(req, res) {
            //session清空!尔后,导向/session路由, 
            req.session.destroy();
            return res.redirect('/session');
        });
    
    module.exports = loginAPI;
    

    访问如图:


    相关文章

      网友评论

        本文标题:nodejs--session&&cookie

        本文链接:https://www.haomeiwen.com/subject/hcmtuftx.html