美文网首页
认清cookie!

认清cookie!

作者: 潼潼爱coding | 来源:发表于2019-03-20 14:16 被阅读0次

    啥是cookie?

    cookie是一小段文本信息,伴随着用户请求在web服务器和浏览器之间传递
    用于解决 "如何记录客户端的用户信息"

    cookie存在哪里?

    cookie 是存在用户硬盘中,用户每次访问站点时,Web应用程序都可以读取 Cookie 包含的信息。当用户再次访问这个站点时,浏览器就会在本地硬盘上查找与该 URL 相关联的 Cookie。如果该 Cookie 存在,浏览器就将它添加到request header的Cookie字段中,与http请求一起发送到该站点。

    cookie如何添加?

    • 客户端设置:js提供api -- document.cookie
      ⚠️注意:document.cookiecookie的名和值中不能出现分号、逗号、等号和空格,每一个key之间通过分号和空格来分割。
    document.cookie = 'name=value; maxAge=3000; path=/; domain=xx.com; secure'
    

    设置多个cookie
    通过document.cookie的方式设置cookie每次只能设置一个,写多个会如何呢?

    document.cookie = 'cookie1=value1; cookie2=value2'
    

    尝试一下,会发现只有第一个cookie1设置成功,cookie2被无视,因此设置多个cookie,最简单就是多次调用document.cookie

    • 服务端设置:http响应头
      浏览器发出的有些请求返回头中有Set-Cookie的字段,服务器通过这个字段告知浏览器它需要设置的cookie,然后浏览器检查一下设置的内容是否符合浏览器对cookie的要求,符合条件则设置成功
      ⚠️注意:响应头里set-cookie字段可以有多个,每一个对应一个要设置的cookie,且只能对应一个。
    示例

    cookie如何获取?

    • 客户端主动获取
      同样是js提供的api -- document.cookie
     var cookies = document.cookie
    
    • 请求头中携带
      浏览器发送请求时,在请求的头中会自动将“符合条件”的cookie带上。
      既然是请求头中携带的,那么我们通过ajax发送请求的时候,能否顺便设置一下cookie呢?
      var xhr = new XMLHttpRequest();
      xhr.open('GET', url, true);
      xhr.withCredentials = true;
      xhr.setRequestHeader('Cookie', "key=value");
      xhr.send(null);
    

    xhr.withCredentials:

    一般跨域请求的时候,比如A域接收B域的请求时,接收不到B域的cookies,也就是说,A服务器的request.getCookies() 为空。解决这个问题,一般把XMLHttpRequest这个对象的withCredentials属性设置为true

    实验一下可以发现,我们设置的cookie并没有生效,并且chrome浏览器下我们会看到一行报错

    Refused to set unsafe header "Cookie"

    因为浏览器的安全限制,我们不能自己随便设置请求头中的cookie。

    cookie有哪些属性?

    属性名 说明
    domain 限制cookie的使用范围,只能在domain值范围内才能访问该cookie
    path domain和path共同限制了课访问该cookie的url,如果某个cookie限制了path='/abc',那么只有'domain/abc'下的所有url可以访问该cookie
    expires/max-age cookie的过期时间,默认设置为session,即页面关闭后cookie会被清理。
    expires 是 http/1.0协议中的选项,在新的http/1.1协议中expires已经由 max-age 选项代替。expires必须是 GMT 格式的时间。
    max-age的单位为秒,cookie失效时刻 = 创建时刻 + max-age
    httpOnly 如果被标记为httpOnly,那么document.cookie的方式就无法获取到该cookie。同样的,我们通过js来设置cookie的,也无法被标记为httpOnly。
    这个值只能通过请求的响应头来设置。默认情况下,cookie不会带httpOnly选项。
    secure 对于被标记为Secure的cookie,只有当请求是HTTPS或者其他安全协议时,该cookie 才能被访问到。
    同样的,也只有在HTTPS或者其他安全协议时,我们也才能通过js设置secure的cookie。
    sameSite 谷歌开发的一种安全机制,该属性表示 Cookie 不随着跨域请求发送,其目的是尝试阻止CSRF。

    对于domain值的要求

    • 自身:domain的值可以设置为本身。
    • 向下:所有子域名

    如果当前页面的域名是 sub.test.com, 那么 domain 可以设置为.sub.test.com。允许所有sub.test.com的子域名访问,如xx.sub.test.com、xx.xx.sub.test.com。

    • 向上:父级域名,直到顶级域名的下一级

    如果当前页面的域名是sub.test.com, 那么domain可以设置为test.com。但是不能设置为.com。因为.com属于Top-Level Domain。

    cookie的缺点?

    • 安全性弱:由于cookie在http中是明文传递的,其中包含的数据都可以被他人访问,可能会被篡改、盗用。
    • 大小限制:cookie的大小限制在4kb左右,不适合大量存储。
    • 增加流量:cookie每次请求都会被自动添加到Request Header中,无形中增加了流量。cookie信息越大,对服务器请求的时间越长。

    cookie插件

    tiny-cookie(vue-cookie)

    /*!
     * tiny-cookie - A tiny cookie manipulation plugin
     * https://github.com/Alex1990/tiny-cookie
     * Under the MIT license | (c) Alex Chao
     */
    
    !(function(root, factory) {
    
      // Uses CommonJS, AMD or browser global to create a jQuery plugin.
      // See: https://github.com/umdjs/umd
      if (typeof define === 'function' && define.amd) {
        // Expose this plugin as an AMD module. Register an anonymous module.
        define(factory);
      } else if (typeof exports === 'object') {
        // Node/CommonJS module
        module.exports = factory();
      } else {
        // Browser globals 
        root.Cookie = factory();
      }
    
    }(this, function() {
    
      'use strict';
    
      // The public function which can get/set/remove cookie.
      function Cookie(key, value, opts) {
        if (value === void 0) {
          return Cookie.get(key);
        } else if (value === null) {
          Cookie.remove(key);
        } else {
          Cookie.set(key, value, opts);
        }
      }
    
      // 检查是否启用了cookie
      Cookie.enabled = function() {
        var key = '__test_key';
        var enabled;
    
        document.cookie = key + '=1';
        enabled = !!document.cookie;
    
        if (enabled) Cookie.remove(key);
    
        return enabled;
      };
    
      // 根据key名得到cookie的值
      Cookie.get = function(key, raw) {
        if (typeof key !== 'string' || !key) return null;
    
        key = '(?:^|; )' + escapeRe(key) + '(?:=([^;]*?))?(?:;|$)';
    
        var reKey = new RegExp(key);
        var res = reKey.exec(document.cookie);
    
        return res !== null ? (raw ? res[1] : decodeURIComponent(res[1])) : null;
      };
    
      // 在不解码的情况下获取cookie的值。
      Cookie.getRaw = function(key) {
        return Cookie.get(key, true);
      };
    
      // 设置cookie的值
      Cookie.set = function(key, value, raw, opts) {
        if (raw !== true) {
          opts = raw;
          raw = false;
        }
        opts = opts ? convert(opts) : convert({});
        var cookie = key + '=' + (raw ? value : encodeURIComponent(value)) + opts;
        document.cookie = cookie;
      };
    
      // 在不编码的情况下设置cookie的值
      Cookie.setRaw = function(key, value, opts) {
        Cookie.set(key, value, true, opts);
      };
    
      // 用指定的键删除cookie
      Cookie.remove = function(key) {
        Cookie.set(key, 'a', { expires: new Date() });
      };
    
      // 工具函数
      // ---------------
    
      // 转义特殊字符
      function escapeRe(str) {
        return str.replace(/[.*+?^$|[\](){}\\-]/g, '\\$&');
      }
    
      // 将对象转换为cookie选项字符串。
      function convert(opts) {
        var res = '';
    
        for (var p in opts) {
          if (opts.hasOwnProperty(p)) {
    
            if (p === 'expires') {
              var expires = opts[p];
              if (typeof expires !== 'object') {
                expires += typeof expires === 'number' ? 'D' : '';
                expires = computeExpires(expires);
              }
              opts[p] = expires.toUTCString(); // 可根据世界时 (UTC) 把 Date 对象转换为字符串
            }
    
            if (p === 'secure') {
              if (opts[p]) {
                res += ';' + p;
              }
    
              continue;
            }
    
            res += ';' + p + '=' + opts[p];
          }
        }
    
        if (!opts.hasOwnProperty('path')) {
          res += ';path=/';
        }
    
        return res;
      }
    
      // 按给定字符串返回expires
      function computeExpires(str) {
        var expires = new Date();
        var lastCh = str.charAt(str.length - 1);
        var value = parseInt(str, 10);
    
        switch (lastCh) {
          case 'Y': expires.setFullYear(expires.getFullYear() + value); break;
          case 'M': expires.setMonth(expires.getMonth() + value); break;
          case 'D': expires.setDate(expires.getDate() + value); break;
          case 'h': expires.setHours(expires.getHours() + value); break;
          case 'm': expires.setMinutes(expires.getMinutes() + value); break;
          case 's': expires.setSeconds(expires.getSeconds() + value); break;
          default: expires = new Date(str);
        }
    
        return expires;
      }
    
      return Cookie;
    
    }));
    
    

    相关文章

      网友评论

          本文标题:认清cookie!

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