zoukankan      html  css  js  c++  java
  • 自定义实现getCookie /setCookie方法

    1. 原生实现

    使用http实现服务时,处理cookie是从回调函数的request参数从请求头中获取cookie;

    let cookies = querystring.parse(req.headers.cookie, "; ");
    res.end(cookies['name']);

    通过response参数设置cookie响应头。

    res.setHeader('Set-Cookie', ['name=lyra', 'age=18']);

    但是操作方法不符合用户的操作习惯。

    2. 封装实现

    可以通过封装方法实现符合用户习惯的getCookie/setCookie方法。

    其中为了避免服务器返回的cookie被用户任意修改,可以将cookie进行签名,如果修改,则服务器端不识别修改后的cookie。

    let http = require('http');
    let querystring = require('querystring');
    
    let signedCookie = function(value) {
      // 将value通过密钥secret签名后输出base64格式的内容
      return require('crypto').createHmac('sha256', 'secret')
                // cookie将+/去除
                .update(value.toString()).digest('base64').replace(/[+/]/g, '');
    }
    http.createServer(function(req, res) {
      res.getCookie = function(name) {
        let cookies = querystring.parse(req.headers.cookie, "; ");  
        if (cookies[name]) {
          let [value, signedValue] = cookies[name].split('.');
          if (signedValue) {// 获取加盐的内容需要进行校验
            if (signedCookie(value) === signedValue) {
              return value;
            }
          } else {
            return cookies[name]
          }
        }
        return '';
      }
      let arr = [];
      res.setCookie = function(key, value, options) { 
        let optionsArr = []; 
        // 如果服务器端设置的cookie是要求签名的,则内容需要使用加盐算法处理
        if(options.signed) {
          value = value+ '.' + signedCookie(value);
        }
        optionsArr.push(`${key}=${value}`);
        if(options.domain) {
          optionsArr.push(`domain=${options.domain}`);
        } 
        if(options.path) {
          optionsArr.push(`path=${options.path}`);
        }
        if(options.maxAge) {
          optionsArr.push(`max-age=${options.maxAge}`);
        }
        if(options.expires) {
          optionsArr.push(`expires=${options.expires}`);
        }
        if(options.httpOnly) {
          optionsArr.push(`httpOnly=${options.httpOnly}`);
        }
        arr.push(optionsArr.join('; '))
        res.setHeader('Set-Cookie', arr);
      }
      if(req.url === '/read') {
        // 使用设置后的方法可以逐条获取
        res.end(res.getCookie('age'));
      }
      if(req.url === '/write') {
        // 使用封装后的方法可以逐条设置
        res.setCookie('name', 'lyra', {path: '/write', httpOnly: true});
        // signed表示cookie需要要经过签名
        res.setCookie('age', 18, {domain: '.lyra.cn', maxAge: 10, signed: true});
        res.end('writted');
      }
    }).listen(3000);
  • 相关阅读:
    <大学祭>
    使用rest方式修改服务端xml文件
    tsql的奇特语法
    Dandelion
    正则中关于修饰符g以及exec和match区别的一个小demo
    如何将一个盒子在显示在浏览器的正中间
    Js中的this指向问题
    CSS通过边框border-style来写小三角
    用单例模式封装常用方法 utils class v1.0
    JS中检测数据类型的四种方法
  • 原文地址:https://www.cnblogs.com/lyraLee/p/12202825.html
Copyright © 2011-2022 走看看