zoukankan      html  css  js  c++  java
  • Cookie和Session在Node.JS中的实践(三)

    Cookie和Session在Node.JS中的实践(三)

    前面作者写的COOKIE篇SESSION篇,算是已经比较详细的说明了两者间的区别、机制、联系了。阅读时间可能稍长,因为作者本身作图也做了不短时间,都是为了能形象的把COOKIESESSION的运行原理描述出来,但花点时间去阅读理解他们是值得的。因为这个技术点虽然小,但涉及到前后端交互,无论是做前端还是后台,都需要懂。不然,只会遭同事鄙视……所以,为了不被鄙视,还是好好读多点书,充实自己。

    如果还未搞懂COOKIE和SESSION的,建议去看看前面的两篇文章,再来看本篇,本篇主要重在实践,而不会再细讲原理性的东西。

    设置COOKIE

    使用原生NODE会让代码变得更复杂一些,为了方便演示代码这里使用到NODE.JS的框架Express,反正我们主要是讲COOKIE,框架无影响。

    const express = require('express');
    
    var server = express();
    
    server.use('/cnblogs/wljqds', (req, res) => {
        // 给客户端返回一个cookie
        res.cookie('user', 'wljqds', {
            path: '/cnblogs/wljqds',
            maxAge: 20*60*1000
        });
        res.send('ok');
    });
    
    server.listen(8080);
    

    运行结果:(在浏览器中输入localhost:8080/cnblogs/wljqds)

    2018-09-26-16-52-37

    根据cookie篇中的说法,这个时候在响应首部(Response)应该会有Set-Cookie字段(在第一篇中有写到)

    2018-09-26-20-30-50

    path对COOKIE访问的影响

    domain和path字段结合起来就能限制浏览器对COOKIE的访问,在domain都是默认的情况下(一般而言都是根域名),只有path起作用,在COOKIE篇,用博客园为例说明了,在此我们可以用自己的代码说明,在上述代码中我们设置COOKIE的path值为path: '/cnblogs/wljqds',其实只要理解一点下级目录可以用上级目录的cookie,反之不可则容易了,为了说明这种情况,相对上述代码添加一个上级目录路由以及一个下级目录。

    const express = require('express');
    
    var server = express();
    
    // 相对path: '/cnblogs/wljqds'来说,/是上级目录 
    server.use('/', (req, res) => {
        res.send('ok');
    });
    // 相对path: '/cnblogs/wljqds'来说,/cnblogs/wljqds/article是下级目录 
    server.use('/cnblogs/wljqds/article', (req, res) => {
        res.send('ok');
    });
    server.listen(8080);
    

    在运行代码前,我有必要说明一点:前面我们已经保存了一个cookie了,这时候我们只是去查看cookie,验证path对cookie的限制。
    首先,是根路径是否能访问cookie,访问根路径localhost:8080/

    2018-09-26-17-15-42

    localhost:8080根路径下,没有任何的cookie,说明上级不能访问下级的cookie。
    另外一个在此由于篇幅问题不在演示,读者们可以用代码自己尝试,记住一点:cookie对下级目录可以访问,但上级不可以。

    设置COOKIE签名

    其实在COOKIE篇中,有一个非常重要的概念没有谈及,那就是COOKIE签名,一些重要的信息保存在COOKIE,这时候是要COOKIE的。在这里补充知识,并且说明如何设置COOKIE签名。

    首先COOKIE签名的作用是防止COOKIE被篡改!,通过在服务端验证签名从而能做到防止COOKIE篡改。

    函数签名这个概念,需要从两个方面理解:
    1.服务端把一个带签名COOKIE发送到客户端:服务端会生成一个秘钥,再使用加密算法比如HMAC-SHA256算法对COOKIE数据和秘钥一起加密得到一个签名,然后将这个签名加到COOKIE中,再发送给客户端。

    2018-09-26-19-48-28

    2.服务端对客户端发送过来的COOKIE进行签名检验:当客户端再次发起请求的时候会将这个已经签名的COOKIE一起发送到服务器中,服务器中会把之前生成的秘钥跟COOKIE数据再次通过相同的算法进行加密,得到一个签名,再与发送过来的签名作对比,如果签名不相等,则证明COOKIE已经被篡改了!

    2018-09-26-20-16-51

    通过上述的原理,代码实现COOKIE签名

    const express = require('express');
    const cookieParse = require('cookie-parser');
    var server = express();
    
    // 添加一个秘钥,通过秘钥生成签名与验证
    server.use(cookieParse('qvqonvpasvoqsgf'));
    server.use('/cnblogs/wljqds', (req, res) => {
        // 给客户端返回一个cookie
        res.cookie('user', 'wljqds', {
            path: '/cnblogs/wljqds',
            maxAge: 20*60*1000,
            signed: true  //设置签名为true
        });
        // 使用signedCookies,而不是cookies.因为是签名的COOKIE
        console.log(req.cookies); 
        res.send('ok');
    });
    
    server.listen(8080);
    

    控制台中输出: { user: 'wljqds' },浏览器中查看COOKIE,COOKIE值已经是加了一串签名。

    2018-09-26-20-36-31

    读取COOKIE

    读取cookie用到一个中间件cookie-parser,非常简单,需要注意一点就是。如果是签名的COOKIE,必须使用req.signedCookies

    const express = require('express');
    const cookieParse = require('cookie-parser');
    var server = express();
    
    server.use(cookieParse());
    
    server.use('/cnblogs/wljqds', (req, res) => {
        // 给客户端返回一个cookie
        res.cookie('user', 'wljqds', {
            path: '/cnblogs/wljqds',
            maxAge: 20*60*1000
        });
        // 输出请求中的cookie
        console.log(req.cookies);
        // 删除一个COOKIE
        res.clearCookies('user');
        res.send('ok');
    });
    
    server.listen(8080);
    

    运行结果在控制台中输出:{ user: 'wljqds' },简单暴力。

    session

    session的实践,记忆犹新,大一在学校上网站设计的课程,我们老师问网站用什么来维持登录状态……班上的人居然没人能回答,然后自己回宿舍去找相关资料,为的就是下次跟老师讨论……
    session是依赖cookie的,所以它同样需要中间件cookie-parser,另外还需要cookie-session中间件。session配合项目使用就能明白他的强大。在此只做一个session的简单小例子:

    使用session,简单的记录访问次数

    const express = require('express');
    const cookieParser = require('cookie-parser');
    const cookieSession = require('cookie-session');
    
    var server = express();
    
    server.use(cookieParser('hnyetfsdnyth'));
    // 设置session相关信息
    server.use(cookieSession({
        // keys是session的秘钥,越多越好,循环使用keys进行加密
        keys: ['aaa', 'bbb', 'ccc'],
        // session的名字
        name: 'sessID',
        // session的ID,不设置默认是关闭浏览器就过期
        maxAge: 20*60*1000
    }));
    
    server.get('/', (req, res) => {
        // 
        if(req.session['count'] == null) {
            // 设置COOKIE中一个count字段
            req.session['count'] = 1;
        } else {
            req.session['count']++;
        }
        // 读取请求中的session
        console.log(req.session['count']);
        res.send('ok');
    })
    server.listen(8080);
    

    每进行一次页面刷新,则相当于一次访问,输出台:
    2018-09-26-21-08-30

    总结:

    首先先说自己的写作感受,作者本人是第一次写文章,也不知道自己能表达清楚或者错误理解,后面会继续写自己所实践过的技术。
    然后,COOKIE和SESSION的方方面面都已经写完了,不明白的可以讨论,作者花了挺多时间在作图上,不明白原理的话,图文结合多想几次,直到明白,这种技术点一定要半桶水,不然只会害了自己,坑了同事。
    再说,这三篇文章其实涉及到的不止COOKIE和SESSION,前后端的交互作者都交待的挺清楚的,读者们能从我的文章中得到新的知识就OK,写文章的乐趣就在于分享
    下次见。


    如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!

    Reference

    1.https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Set-Cookie
    2.https://www.cnblogs.com/moyand/p/9047978.html
    3.https://nodejs.org/dist/latest-v8.x/docs/api/http.html#http_response_setheader_name_value

  • 相关阅读:
    视觉slam十四讲课后习题ch3-7
    视觉slam十四讲课后习题ch3-6
    视觉slam十四讲课后习题ch3--5题
    (原创)遗传算法C++实现
    (笔记):组合and继承之访问限制(二)
    (笔记):组合and继承之访问限制(一)
    (笔记):初始化列表之初始化顺序
    (笔记):构造函数之初始化列表
    笔记:构造函数易错点
    (笔记):构造函数与析构函数
  • 原文地址:https://www.cnblogs.com/wljqds/p/node_cookie_session.html
Copyright © 2011-2022 走看看