黑马程序员技术交流社区

标题: 谈谈Cookie [打印本页]

作者: 天树123    时间: 2020-4-22 14:43
标题: 谈谈Cookie
一、前言
最近由于Chrome 80+对第三方cookie进行了限制,虽然没有像最新版的safari和Firefox一样默认禁止第三方cookie,但是离完全禁止第三方cookie也不远。但因此也给我们前端开发人员带来了一些影响,第三方cookie不能正常携带,造成了许多请求有问题。

二、cookie的用途
众所周知HTTP请求是无状态请求,简言之即是HTTP请求不知道请求是否是来自同一个客户端,对于仅是访问无需用户标识的静态资源这是没有问题,但是如果我们在天猫、或者淘宝上购买东西时,服务端无法知道请求是否来自同一个用户,这就很糟糕了。所以HTTP协议需要占用浏览器的一小块存储,存储当前访问用户的一些状态,然后每次发起HTTP请求,请求中就会携带这些状态,从而让服务器知道你是谁。cookie技术就是为了解决这个问题,让无状态的HTTP协议拥有一小块记忆。cookie是一小段数据文本,是服务端为了辨别用户身份而储存在用户本地终端上的加密数据。可分为内存cookie和硬盘cookie,内存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的主要信息包含如下。
1、cookie-name=cookie-value:cookie的名/值对;
2、Expires=<date>[可选]:cookie的最长有效时间;
3、Max-Age=<non-zero-digit>[可选]:cookie失效之前需要经过的秒数,当Expires 和Max-Age均存在时,Max-Age优先级更高。;
4、Domain=<domain-value>[可选]:指定cookie的需要送达的域名,偌没有指定,那么默认值为当前访问地址中的主机部分(但是不包含子域名);
5、Path=<path-value>[可选]:指定一个URL路径,这个路径必须出现在要请求的资源的路径中才可以发送cookie首部;
6、Secure[可选]:只有在请求使用SSL和HTTPS协议的时候才会发送cookie到服务器;
7、HttpOnly[可选]:设置了HttpOnly属性的cookie不能使用JavaScript经由  document.cookie属性、XMLHttpRequest和Request APIs进行访问;
8、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






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2