美文网首页
Cookie&Session的使用

Cookie&Session的使用

作者: 林木木road | 来源:发表于2018-09-24 17:32 被阅读0次

    定义:cookie指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。

    格式:cookie以键值对的形式存储于浏览器中,key=value。不同cookie之间用分号";"隔开, key1=value1;key2=value2;...;keyN=valueN

    工作机制:当用户首次访问浏览器时,服务器将向浏览器写回一个cookie;在下一次访问服务器时,服务器则可以通过浏览器的cookie到服务器的session的存储空间中找到对应的数据。

    cookie的作用图示

    注:如果cookie不设置过期时间,则默认在浏览器关闭时就删除

    浏览器cookie截图

    一个域名下面可能存在着很多个cookie对象。cookie的多个属性列举如下:

    • name字段为一个cookie的名称。
    • value字段为一个cookie的值。
    • domain字段为可以访问此cookie的域名。
      非顶级域名,如二级域名或者三级域名,设置的cookie的domain只能为顶级域名或者二级域名或者三级域名本身,不能设置其他二级域名的cookie,否则cookie无法生成。
      顶级域名只能设置domain为顶级域名,不能设置为二级域名或者三级域名,否则cookie无法生成。
      二级域名能读取设置了domain为顶级域名或者自身的cookie,不能读取其他二级域名domain的cookie。所以要想cookie在多个二级域名中共享,需要设置domain为顶级域名,这样就可以在所有二级域名里面或者到这个cookie的值了。
      顶级域名只能获取到domain设置为顶级域名的cookie,其他domain设置为二级域名的无法获取。
    • path字段为可以访问此cookie的页面路径。 比如domain是abc.com,path是/test,那么只有/test路径下的页面可以读取此cookie。
    • expires/MaxAge 字段为此cookie超时时间。若设置其值为一个时间,那么当到达此时间后,此cookie失效。不设置的话默认值是Session,意思是cookie会和session一起失效。当浏览器关闭(不是浏览器标签页,而是整个浏览器) 后,此cookie失效。
    • Size字段 此cookie大小。
    • httpOnly字段 若此属性为true,前台则只有在http请求头中会带有此cookie的信息,而不能通过document.cookie来访问此cookie。
    • secure 字段 设置是否只能通过https来传递此条cookie

    NodeJS中使用cookie

    1. 搭建基本的服务器

    2. 处理响应的时候

    (1) 声明全局的session global mySession = {};

    (2) 处理登陆逻辑 /login ——完成登陆,记录用户状态,并且写回一个cookie

    • 检验登陆逻辑,从数据库中获取用户信息
    • 生成cookie值
    • 关联cookie,存储到服务器的全局session中 global.mySession[cookieValue] = obj;
    • 写回cookie
      res.setHeader('set-cookie', 'cookie=cookieValue;[expires=过期时间][domain=允许访问的域名][;path=允许访问路径][;secure=约定传递方式][;httpOnly=布尔值][;size=大小]');

    (3) 处理显示登陆状态的响应/result——通过cookie来获取,并且响应用户再session中的数据

    • 从浏览器请求报文头中获取cookie字符串 req.headers.cookie => 'key1=value1;key2=value2;...'
    • 处理cookie字符串,取得存储用户状态的cookie值, 首先以";"作为关键字对字符串进行切割,再遍历数组元素,对每个cookie键对进行切割
    • 从全局session中获取用户信息并写回浏览器 res.end(JSON.stringify(global.mySession[cookieValue]))
    1. 为保证安全性,cookie需要适当加密
      依赖包jsonwebtoken npm install jsonwebtoken -S

    (1) 对称加密

    • 加密: let token = jwt.sign({xxx: xxx}, 'shhhhh');
    • 解密: let decoded = jwt.verigy(token, 'shhhhh'); =>{xxx: xxx}

    (2)非对称加密——公密私解 or 私密公解

    • 读取公钥pub.pem文件进行加密
     let cert = fs.readFileSync("./pub.pem");
     let token = jwt.sign({xxx:xxx}, cert, {algorithm: 'RS256'});
    
    • 读取私钥priv.pem文件进行解密
    let cert = fs.readFileSync("./priv.pem");
    let token = jwt.verify(token, cert, (err, decoded) {
      //decoded = {xxx: xxx}
    });
    
    代码实现:
    const http = require("http");
    const fs = require("fs");
    const path = require("path");
    const url = require("url");
    const jwt = require("jsonwebtoken");        //加密依赖包
    
    //模拟一个session
    global.mySession ={};
    //模拟一个用户列表
    let myUserlist = [
      {
        id: 0,
        username: 'jack'
      },
      {
        id: 1,
        username: 'john'
      }
    ];
    let pub = fs.readFileSync('./public.key');      //读取公钥文件
    let priv = fs.readFileSync('./private.key');    //读取私钥文件
    
    const server = http.createServer((req, res) => {
      if(req.url.startsWith('/user_login')) {         //登陆操作
        //获取请求报文的参数
        let query = url.parse(req.url, true).query;
        //遍历用户列表(数据库),得到用户id(严格来讲,这里还需要各种校验),返回token
        for(let i = 0; i < myUserlist.length; i ++) {
          if(myUserlist[i].username.toLowerCase() === query.username.toLowerCase()) {
            //使用私钥生成一个加密的cookie值
            let cookieValue = `${myUserlist[i].id}_${Date.now()}`;
            let token = jwt.sign(cookieValue, priv, {algorithm: 'RS256'});  //最后一个参数可省
            //关联cookie值,存入到全局的session中
            global.mySession[cookieValue] = {name: query.username};
            //写回cookie给前台
            res.setHeader('set-cookie', `id=${token}`);
            res.end();
          }
        }
      } else if (req.url.startsWith('/result')) {       //同一域名下的不同页面,可以通过cookie共享数据
        //从前台页面中得到token值
        let cookies = req.headers.cookie.split(";").map(c => c.split("="));   //[[cookie1, value1], [cookie2, value2], ...]
        let user;
        cookies.forEach(c => {
          if(c[0].trim() === 'id') {
            //使用公钥解密cookie,并从session中读取对应的值
            jwt.verify(c[1], pub, (err, decoded) => {
              user = global.mySession[decoded];
            });
          }
        })
        //返回页面
        fs.readFile('./result.html', (err, data) => {
          res.writeHeader(200);
          res.end(data.toString().replace('{{user}}', JSON.stringify(user)));
        })
    
      } else if (req.url.startsWith('/login')) {          //登陆页面
        //返回加载页面
        fs.readFile('./login.html', (err, data) => {
          res.writeHeader(200);
          res.end(data);
        })
      }
    });
    
    server.listen(8888, () => {
      console.log("The server is running...");
    })
    

    相关文章

      网友评论

          本文标题:Cookie&Session的使用

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