美文网首页
nodejs之cookie和session

nodejs之cookie和session

作者: _BuzzLy | 来源:发表于2020-04-27 19:01 被阅读0次

    由于最近工作需要又将node捡了起来。翻了下之前的笔记,想着把几篇比较详细的整理下分享出来。第一篇就来说说经常会用到的cookie&session。

    由来

    众所周知http是一个无状态的协议,服务端无法跟踪客户端的状态。那么就会导致一个问题,如我们以管理员身份登录一个后台管理系统,登录成功后跳转到管理页面,那在我们进行操作时,服务器怎么知道我们是否已经登录过了呢?

    cookie

    为了解决上面的问题,cookie诞生了。

    cookie是http协议中的一部分,浏览器向服务器发请求,成功后服务器向浏览器返回一个cookie,那么以后浏览器向服务器发送的所有请求都会携带这个cookie。

    首先安装express框架,当然你也可以使用koa。这里演示代码都是express。
    在express中cookie不是自带的,所以需要安装对应的中间件进行操作,koa中的cookie就是框架自带的就不需要另外安装。

    安装cookie-parser中间件

    npm i cookie-parser -D

    写cookie

    安装成功后,先引入cookie-parser。然后在任意路由中去尝试写一个cookie

    const express = require('express');
    const cookieParser = require('cookie-parser');
    
    let server = express();
    server.listen(8080);
    
    // 使用中间件
    server.use(cookieParser());
    
    server.get('/index',(req, res) => {
        // 使用了中间件后就可以访问req和res上的cookies对象
        console.log(req.cookies);
        // 写cookie
        res.cookie('num', 10, {
            // domain: 'xxx.com',
            // path: '/',
            maxAge: 24 * 3600 * 1000
        })
        res.send('ok');
    })
    

    cookie的读取和设置都很简单,设置的时候有一些可选参数,

    • domain:存储的域名,cookie是不跨域的,并且存储在主域名中子域名是可以访问到的,但是如果存在子域名中那么主域名是无法访问的。所以这里一般是存在主域名,避免子域名访问不到cookie。
    • path:存储路径,与domain类似,所以一般也是指定根路径。
    • maxAge:有效期(毫秒)

    运行下代码,然后到浏览器中查看刚刚写入的cookie


    在这里插入图片描述

    打开浏览器F12,到Application中找到Cookies,就可以看到刚刚写入的cookie,名字和值以及有效期都是我们设置的。再次刷新后我们也可以在命令行中看到服务器打印的cookie。


    在这里插入图片描述
    简单的cookie读写就完成了。

    安全隐患

    这里我们可以知道cookie是存在浏览器中的,并且请求服务器的时候会一并带过去。这样就一定会有安全隐患,我们先把服务器写cookie的逻辑注释掉,重新运行服务器,然后尝试在浏览器中手动修改cookie。


    在这里插入图片描述

    这里我们将值修改为10000。刷新页面后在命令行中可以看到服务器获取的值就是10000。


    在这里插入图片描述
    cookie就这样很容易的在浏览器中被我们修改了。如果cookie存了一些比较重要的数据,后果会非常严重。

    cookie签名
    怎么样才能做到让服务器验证cookie准确性,让服务器发现cookie是否被人为修改。
    就要用到cookie签名。修改下服务器代码。

    // 密钥
    server.use(cookieParser(
      'dasdasdasdasfewg315nkl23k1ml41m24kl1nm5kol312n5kl32n5oj3n4oi1jm4o1k2m4'
    ));
    

    在使用cookieParser中间件的时候加入一个签名密钥,一般是随机生成的一个字符串
    然后在设置cookie的时候加入几个参数。

    server.get('/index',(req, res) => {
        // 签名后的cookie需要通过signedCookies访问
        console.log(req.signedCookies);
        res.cookie('num', 10, {
            // httpOnly: true,
            // secure: true,
            signed: ture
            maxAge: 24 * 3600 * 1000
        })
        res.send('ok');
    })
    
    • httpOnly:设置cookie只能由服务器操作,前台看不到
    • secure:只有在https的情况下才能使用cookie
    • singed:设置cookie是否签名

    这里我先现开启签名。然后运行代码

    在这里插入图片描述
    可以看到这回的cookie是一串乱码。将乱码复制出来是这样的。
    s%3A10.y4%2BaUbiQxjUS%2FvaGtU%2BaZnAZ9WxVHXy3O0zr%2BgoCdGk
    %3A代表":",转换下得到如下:
    s:10.y4%2BaUbiQxjUS%2FvaGtU%2BaZnAZ9WxVHXy3O0zr%2BgoCdGk
    通过以上得出签名后的cookie格式为:
    s:值.签名
    这样如果我们尝试修改其中的值,还会不会生效了呢?
    将服务器设置cookie的代码注释掉,只打印cookie,然后在浏览器中修改cookie。
    在这里插入图片描述 在这里插入图片描述
    修改后的cookie因为无法通过服务器的签名验证,所以是无法获取的。这样就确保了cookie的安全性,虽然签名可以增加cookie的安全性,但是增大体积,由于cookie只有4k的存储空间,所以我们只签名重要的信息。

    session

    cookie 虽然很方便,但是使用 cookie 有一个很大的弊端,就是存储在浏览器,虽说可以对cookie进行签名,但是也不能保证cookie的绝对安全,并且将重要的信息存在客户端本身就是不安全的事情。同时cookie也受限于大小。为了解决这些问题session也诞生了。

    session 中的数据是保留在服务器端的。session不会单独存储,会有标识,这个标识叫做session_id 或者 token。并且session是强制加密的。

    同样我们需要另一个中间件操作session,cookie-session
    npm i cookie-session -D
    使用方式与cookie-parser类似,先引入cookie-session

    const cookieSession = require('cookie-session');
    

    然后进行循环密钥签名,密钥一般是通过程序生成的,可能几千几万条,这里方便演示,只写几条。

    server.use(cookieSession({
      keys: ['dasdas21fsdffedsfds4das21321', 'safdas454325235325trgtrthdfthd', '21ed2rf3245r23r2354r235235'],
      maxAge: 20 * 60 * 1000      // 有效期20分钟
    }));
    

    然后在接口中设置和获取session

    server.get('index', (req, res) => {
        console.log(req.session);
        res.session['num'] = 10;
        res.send('ok');
    });
    

    运行代码,打开浏览器调试工具找到cookies,


    在这里插入图片描述

    cookie中有两个值,一个是session,一个是session.sig
    将服务器中设置session的代码注释掉,再刷新页面,可以看到命令行中就打印了我们设置的session值。


    在这里插入图片描述
    就算其他用户通过session劫持拿到了我们的session值,但是每个用户的session.sig签名是通过循环密钥生成的,数量庞大的循环密钥相同的几率很小。并且在浏览器手动修改session后,服务器也会感知到这个session和session.sig不是对应的。确保数据的安全性。同时也可以通过更换循环密钥和减少session有效期来提升安全性。

    需要注意的是session是存在服务器的文件中。读写比较消耗性能。我们可以将其保存在redis、内存、数据库中以优化性能。(如使用mysql-session)

    相关文章

      网友评论

          本文标题:nodejs之cookie和session

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