Cookie&Session的使用

2018-09-24  本文已影响0人  林木木road

定义: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

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

  1. 为保证安全性,cookie需要适当加密
    依赖包jsonwebtoken npm install jsonwebtoken -S

(1) 对称加密

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

 let cert = fs.readFileSync("./pub.pem");
 let token = jwt.sign({xxx:xxx}, cert, {algorithm: 'RS256'});
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...");
})
上一篇下一篇

猜你喜欢

热点阅读