聊一聊Cookie那些事儿

聊一聊Cookie那些事儿

技术杂谈小彩虹2021-08-18 9:08:46220A+A-

前言

最近由于Chrome 80+对第三方cookie进行了限制,虽然没有像最新版的safariFirefox一样默认禁止第三方cookie,但是离完全禁止第三方cookie也不远。但因此也给我们前端开发人员带来了一些影响,第三方cookie不能正常携带,造成了许多请求有问题。

cookie的用途

众所周知HTTP请求是无状态请求,简言之即是HTTP请求不知道请求是否是来自同一个客户端,对于仅是访问无需用户标识的静态资源这是没有问题,但是如果我们在天猫、或者淘宝上购买东西时,服务端无法知道请求是否来自同一个用户,这就很糟糕了。所以HTTP协议需要占用浏览器的一小块存储,存储当前访问用户的一些状态,然后每次发起HTTP请求,请求中就会携带这些状态,从而让服务器知道你是谁。cookie技术就是为了解决这个问题,让无状态的HTTP协议拥有一小块记忆。cookie是一小段数据文本,是服务端为了辨别用户身份而储存在用户本地终端上的加密数据。可分为内存cookie和硬盘cookie,内存cookie由浏览器自己维护,写在内存里,在浏览器关闭时,就消失了。对于设定了过期时间的cookie是硬盘cookie,会存储在文件内,除非用户手工清理或到了过期时间,否则cookie是一直存在的。

第三方cookie

第一方cookie就是当前访问域名一致的网址种下的cookie信息,而第三方cookie是其它站点种下的cookie,比如我们访问天猫的网站,可以看到如下的cookie信息。

天猫cookie
我们可以看到除了天猫域名种下的 cookie之外,还有需要第三方站点如 taobao.commmstat.com种下的 cookie,而这些就是第三方 cookie。当然了第三方 cookie的存在肯定是为了做一些事情的,比如我们前端经常做的前端异常监控,日志卖点等都需要第三方 cookie的配合。

设置cookie

cookie可以通过客户端的document.cookie方法进行设置,如下是MDN提供客户端的设置cookie的方法。

var docCookies = {
  getItem: function (sKey) {
    return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[-.+*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
  },
  setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
    if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
    var sExpires = "";
    if (vEnd) {
      switch (vEnd.constructor) {
        case Number:
          sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
          break;
        case String:
          sExpires = "; expires=" + vEnd;
          break;
        case Date:
          sExpires = "; expires=" + vEnd.toUTCString();
          break;
      }
    }
    document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
    return true;
  },
  removeItem: function (sKey, sPath, sDomain) {
    if (!sKey || !this.hasItem(sKey)) { return false; }
    document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + ( sDomain ? "; domain=" + sDomain : "") + ( sPath ? "; path=" + sPath : "");
    return true;
  },
  hasItem: function (sKey) {
    return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[-.+*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
  },
  keys: /* optional method: you can safely remove it! */ function () {
    var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
    for (var nIdx = 0; nIdx < aKeys.length; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); }
    return aKeys;
  }
};

服务端也可以设置cookie,通过响应头的set-cookie进行cookie的设置。其中set-cookie的主要信息包含如下。

  • cookie-name=cookie-valuecookie的名/值对;
  • Expires=<date>[可选]:cookie的最长有效时间;
  • Max-Age=<non-zero-digit>[可选]:cookie失效之前需要经过的秒数,当ExpiresMax-Age均存在时,Max-Age优先级更高。;
  • Domain=<domain-value>[可选]:指定cookie的需要送达的域名,偌没有指定,那么默认值为当前访问地址中的主机部分(但是不包含子域名);
  • Path=<path-value>[可选]:指定一个URL路径,这个路径必须出现在要请求的资源的路径中才可以发送cookie首部;
  • Secure[可选]:只有在请求使用SSLHTTPS协议的时候才会发送cookie到服务器;
  • HttpOnly[可选]:设置了HttpOnly属性的cookie不能使用JavaScript经由 document.cookie属性、XMLHttpRequestRequest APIs进行访问;
  • SameSite=<None|Strict|Lax>[可选]:设置了第三方cookie是否可以在跨站访问时被携带,Chrome 80+默认是Lax
// 会话 cookie
Set-Cookie: sessionid=38afes7a8; HttpOnly; Path=/
// 持久 cookie
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly

点击这里复制本文地址 以上内容由权冠洲的博客整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

支持Ctrl+Enter提交

联系我们| 本站介绍| 留言建议 | 交换友链 | 域名展示
本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除

权冠洲的博客 © All Rights Reserved.  Copyright quanguanzhou.top All Rights Reserved
苏公网安备 32030302000848号   苏ICP备20033101号-1
本网站由 提供CDN/云存储服务

联系我们