Cookie

79次阅读

共计 58 个字符,预计需要花费 1 分钟才能阅读完成。

cookie

第 1 节 Cookie 快速入门

第 2 节 Cookie_细节

第 3 节 Cookie 案例

第 4 节 JSP 改造 Cookie 案例

正文完
 0

cookie

79次阅读

共计 2485 个字符,预计需要花费 7 分钟才能阅读完成。

0. 从 http 协议的无状态性说起

  • http 是无状态的协议
  • 无连接:处理完一个请求就断开链接(http1.1 以后可以实现长连接)
  • 无状态:上一次会话与下一次会话没有联系。
  • 可以通过 cookie 来维护状态信息。

1. cookie

存储大小:每条的存储空间为 4k;

特点:

- cookie 没有显示的删除函数,可以设置 expire/max-age 过期时间,自动触发浏览器的删除机制。- 服务器通过设置响应头来设置客户端的 cookie,Set-Cookie: cookie- 名 =cookie 值。可以同时添加多个 Set-Cookie,从而设置多个 cookie 的值。- 不允许存储敏感信息(用户名,密码等),一定要存储,要设置 cookie 为 httponly,另外考虑使用 非对称加密
- 浏览器 中的 cookie 数量达到上限后,会删除旧的创建新的,删哪个由浏览器的策略决定
- cookie 通常与 session 一起使用。- 登录时,server 端存储 用户信息相关的 session。- server 端,生成的 sessionid 会放在 cookie 中,对应域名下就有了这个 cookie。- 以后会自动带这个 cookie,server 根据 id 找到 session,获取用户信息。

设置 cookie:

    document.cookie="userId=828";
    document.cookie="userName=hulk"; 
    此时浏览器将会维护两个 cookie,分别为 userId 和 userName;相当于:document.addCookie("userId=828");
    document.addCookie("userName=hulk");
    如果要改变一个 cookie 的值,只需重新赋值,例如:document.cookie="userId=929";

获取 cookie:

var strCookie=document.cookie;
console.log(strCookie); //userId=828; userName=hulk
- 只能一次获取所有的 cookie 的值,而不能指定 cookie 名称来获得指定的值。- 如果在某个页面创建了一个 cookie,那么该页面所在目录中的其他页面也可以访问该 cookie。- 为了控制 cookie 可以访问的目录,需要使用 path 参数设置 cookie。document.cookie="userId=320; path=/shop"; 就表示当前 cookie 仅能在 shop 目录下使用。
  • 常用的 cookie 操作及其函数实现:

    • addCookie(name, value, expireHours):
        function addCookie(name,value,expireHours){var exdate = new Date();    
            exdate.setTime(exdate.getTime() + expireHours * 60 * 60 * 1000);    
              document.cookie = name + "=" + escape(value) + ((expireHours == null) ? "":";expires=" + exdate.toUTCString());
        }
        toUTCString() 方法可根据世界时 (UTC) 把 Date 对象转换为字符串,并返回结果。
    • getCookie(name):
        function getCookie(name){let arr, reg = new RegExp(`^| ${name} = [^;]*;|$`);
            if (arr = document.cookie.match(reg)) return arr[2];
            else return null;
        }
  • cookie 的可选项:

    • expires/max-age: 设置过期时间。

      • expires 是绝对时间,max-age 是相对时间。
      • 如果没有设置过期时间,则表示是一个会话期 cookie,在关闭浏览器后,会被移除。
      • 浏览器支持会话恢复,保留 cookie。
      • 正数,表示 多少秒后失效
      • 负数,该 cookie 是临时 cookie,关闭浏览器就失效,浏览器页不会以任何形式保存该 cookie
      • 为 0,表示删除 cookie
    • domain 和 path:

      • path,设置必须匹配的路径或者子路由才会发送 cookie。如果路径设为 /forums/,那么这个 Cookie 只有在访问 www.example.com/forums 及其子路径时才有效。
      • path 的设置,必须以‘/’结尾
      • domain 的设置,第一个字符必须是‘.’, 比如“.baidu.com”
      • domain 标识指定了哪些主机可以接受 cookie。如果没有设置,则是当前主机(不包含子域名),否则为设置的域名(包含子域名)。
    • secure 和 httponly:

      • secure 标志 cookie 只能通过 https 传输,可以防止 xss 攻击。
      • httponly 表示 cookie 无法通过 javascript 调用,防止中间人劫持。把 cookie 设置为 secure,只保证 cookie 与服务器之间的数据传输过程加密,而保存在本地的 cookie 文件并不加密。如果想让本地 cookie 也加密,得自己加密数据。
    • samesite:可以设置 SameSite:SameSite=Strict SameSite=Lax。则 cookie 不跨域发送。ajax 中设置 xhr.withCredentials = true;

问题:

- 问题:“www.qq.com”与“sports.qq.com”公用一个关联的域名”qq.com”,我们如果想让”sports.qq.com”下的 cookie 被“www.qq.com”访问:- 解答:我们就需要用到 cookie 的 domain 属性,并且需要把 path 属性设置为“/“。例:document.cookie =“username=Darren;path=/;domain=qq.com“- 问题:同域名的资源请求时,会默认带上本地的 cookie,如何优化?- 解答:将静态资源分组,分别放在不同的子域下(子域名请求时,是不会带上父级域名的 cookie 的)

cookie 的跨域问题

  • 域名、端口相同就不算跨域,协议可以不同。

正文完
 0

cookie

79次阅读

共计 3700 个字符,预计需要花费 10 分钟才能阅读完成。

需求场景

一个 Vue 单页应用,A、B、C 三个页面都引用了一个公用的时间选择器。用户在各自页面选择完时间后,A,B,C 页面互相切换时保存选择的时间,在关闭浏览器 tab 后,清除选择的时间,恢复初识值。一开始的想法是使用会话 cookie(不手动设置过期时间),但是会话 cookie 在关闭浏览器 tab 的时候不会被清除。所以决定研究下会话 cookie 何时清除。

cookie

背景

HTTP 是一种无状态的协议,它不对请求和响应之间的通信状态进行保存,即无法根据之前的状态进行本次请求的处理。假如要求登录验证的 web 页面本身无法进行状态的管理,那么每次跳转新页面就要再次登录,或者要在请求报文中附加参数来管理登录状态。无状态协议有它的优点,由于不必保存状态,可以减少服务器的 CPU 及内存资源。为了保留无状态协议这个特征的同时又要解决类似的矛盾问题,于是引入了 cookie。

原理

cookie 技术通过在请求和响应报文中写入 cookie 信息来控制客户端的状态。cookie 会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie 的首部字段信息,通知客户端保存。当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入 cookie 值后发送出去。
服务端发现客户端发送过来的 cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到之前的状态信息。

客户端设置

 // 属性之间由一个分号和一个空格隔开
document.cookie = 'name=value[; expires=date][; domain=domain][; path=path][; secure]'

// 设置多个 cookie
document.cookie = 'name=irene; domain=www.baidu.com';
document.cookie = 'age=18; path=/welcome';

document.cookie 一次只能设置一条 cookie,如果需要设置多条,需要多次设置。客户端可以设置的属性有:expires、max-age、domain、path、secure(https 协议下才能设置成功),不能设置 HttpOnly。

服务器端设置

  Set-Cookie: name=value[; expires=date][; domain=domain][; path=path][; secure]

  // 设置多个 cookie
  Set-Cookie: name=irene; domain=www.baidu.com;
  Set-Cookie: age=18; path=/welcome;

一个 Set-Cookie 只能设置一条 cookie,如果需要设置多条,需要多次使用 Set-Cookie。cookie 除了设置名称和值之外,还可以设置其他的属性。服务端可以设置的属性有:expires、max-age、domain、path、secure、HttpOnly 等。

属性

expires 和 max-age

设置 cookie 的失效时间。expires 的值是一个时间点(cookie 失效时刻 = expires),max-age 的值是秒数(cookie 失效时刻 = 创建时刻 + max-age)。expires 是 http/1.0 协议中的选项,在新的 http/1.1 协议中 expires 已经由 max-age 选项代替。如果两者同时存在,max-age 的优先级高于 expires。max-age 有两种可能值:小于等于 0:有效期为能表示的最早时间;大于 0:有效期为当前时间 + max-age。

// expires
document.cookie='name=irene; expires=Wed, 13 Jun 2019 10:28:27 GMT'
// max-age > 0
document.cookie='name=irene; max-age=3600'
// max-age <= 0
document.cookie='name=irene; max-age=0'

注意:一旦 cookie 从服务器端发送至客户端,服务器端就不存在可以显式删除 cookie 的方法。但可通过覆盖 cookie,实现对客户端 cookie 的删除操作。

domain & path

Domain 设置域名,默认是当前域名。path 设置路径,默认是当前目录。domain 和 path 一起限制了哪些请求可以带上该 cookie。比如上面第二个的 cookie,若请求的 URL 的域名是 juejin.com 或 xxx.juejin.com,并且 URL 的路径是 / 或 子路径 ‘/home’,则浏览器会将此 cookie 添加到该请求的 cookie 头部中。

// 在 https://juejin.im/welcome/frontend 设置如下 cookie,则浏览器 Cookie 面板显示的 domain=juejin.im,path=/welcome
document.cookie = 'name=irene'
// 在 https://juejin.im/welcome/frontend 设置如下 cookie,则浏览器 Cookie 面板显示的 domain=.juejin.im(有前缀.),document.cookie = 'name=irene; domain=juejin.im; path=/welcome/frontend'
// 关于 domain 有无前缀点可参考 http://www.it1352.com/548425.html
HttpOnly

当设置了 HttpOnly,浏览器就不会将该 cookie 添加到非 HTTP 请求的头部。
设置 cookie 是否能通过 js 去访问(读取、修改、删除等)。默认情况下,cookie 不会带 HttpOnly 选项,所以客户端是可以通过 js 代码去访问这个 cookie 的。当 cookie 带 HttpOnly 选项时,客户端则无法通过 js 代码去访问这个 cookie。主要目的是为防止跨站脚本攻击对 cookie 的信息窃取。HttpOnly 只能从服务端设置,不能通过客户端设置。

Secure

设置仅在 HTTPS 安全连接时,才可以发送 cookie。

浏览器对于是否携带 cookie 项的策略

domain-matching

一个字符串(str)匹配(domain-matches)一个给定的域名字符串(domain str)至少需要满足以下条件中的一个:

  1. str 和 domain str 完全相同(转成小写后比较)。
  2. 或者同时满足以下条件:
    2.1 domain str 是 str 的后缀。
    2.2 str 中最后一个不包含在 domain str 中的字符是点(.)。

    domain str = google.com;  str = map.googole.com  =>  符合
    domain str = google.com;  str = map.mgoogle.com  =>  最后一个不包含在 domain str 中的字符是 m,不符合 

    2.3 str 必须是一个域名,而不是 IP 地址。

path-matching

一个请求路径(request-path)匹配(path-matches)一个给定的 cookie-path 至少需要满足以下条件中的一个:

  1. request-path 和 cookie-path 完全一样。
  2. cookie-path 是 request-path 的前缀,并且 cookie-path 的最后一个字符是 /。
  3. cookie-path 是 request-path 的前缀,并且 request-path 中第一个不包含在 cookie-path 中的字符是 /。

注意:domain-matching & path-matching 只是浏览器决定是否携带 cookie 诸多参考项中的其中两个,浏览器还会参考诸如是否过期等项。

实践

问题:

cookie 不设置失效时间的话,默认是会话结束失效,这个会话结束是指浏览器的所有窗口都关闭,还是说这个网站的页面全部关闭就可以了?

具体场景:

Chrome 浏览器开了两个窗口 A B,A 打开了网站 1 的两个标签页(tab1 & tab2)和网站 2 的两个标签页(tab3 & tab4),B 打开了网站 1 的两个标签页(tab1 & tab2)和网站 2 的两个标签页(tab3 & tab4),如果想网站 1 的 cookie 失效的话,是不是把窗口 A B 关于网站 1 的 tab 页关掉就行 还是 需要把浏览器的所有窗口都关闭?

实验对象:

https://segmentfault.com。它的 PHPSESSION 是会话结束失效,所以用来测试。

工具:

通过 chrome://settings/cookies/detail?site=segmentfault.com 查看该网站下的所有 cookie。

结论:

浏览器的所有窗口都关闭,网站 1 的 cookie(会话 cookie)才失效。windows 在浏览器窗口都关闭的情况下,会退出程序,所以 cookie 会失效;mac 在浏览器窗口都关闭的情况下,不会退出程序,所以 cookie 不会失效,需要退出程序 cookie 才失效。

规范

如果一个 cookie 同时设置了 Max-Age 和 Expires 属性,Max-Age 的优先级更高。如果两个都没有设置,UA 会保存该 cookie 直到当前 会话结束。

正文完
 0

cookie

80次阅读

共计 2771 个字符,预计需要花费 7 分钟才能阅读完成。

问题

HTTP 协议是一种无状态的协议,Web 服务器本身不能识别出哪些请求是同一个浏览器发出的,浏览器的每一次请求都是完全孤立的。
web 服务器怎么唯一地标识一个用户,并记录该用户的状态?

会话与状态管理

会话指一个客户端与 web 服务器之间连续发生的一系列请求和响应过程。(就像把电话拿起到最后挂断)。
会话状态指 web 服务器与浏览器在会话过程中产生的状态信息,借助会话状态,web 服务器把属于同一会话中的一系列请求和响应过程关联起来。

web 服务器要从大量的请求消息中区分出哪些请求属于同一会话,即能识别出来自同一个浏览器的访问请求,这需要浏览器对其发出的每个请求消息都进行标识:属于同一个会话中的请求消息都附带同样的标识号,属于不同会话的请求消息附带不同的标识号,这个标识号就称为会话 ID。

servlet 规范中,有两种机制完成会话跟踪:
cookiesession

cookie

是客户端保持 HTTP 状态信息的一种方案。
浏览器访问 web 服务器的某个资源时,由 web 服务器在 HTTP 响应消息头中附带传送给浏览器的一个小文本文件(Set-Cookie 响应头字段)。如:

Set-Cookie: bid=8UKoeCtJT1M; Expires=Sat, 25-Apr-20 04:02:11 GMT; Domain=.douban.com; Path=/

一旦 web 浏览器保存了某个 cookie,那么它在以后每次访问该 web 浏览器时都会在 HTTP 请求头中(Cookie 请求头字段)将这个 cookie 回传给 web 服务器。如:

Cookie: bid=8UKoeCtJT1M;

如果浏览器不支持 Cookie(如大部分手机中的浏览器)或者把 Cookie 禁用了,Cookie 功能就会失效。
不同的浏览器采用不同的方式保存 Cookie。
IE 浏览器会在 C:\Documents and Settings\ 你的用户名 \Cookies 文件夹下以文本文件形式保存,一个文本文件保存一个 Cookie。

创建 cookie

httpServletResponse.addCookie(cookie);
该方法并不修改之前的 Set-Cookie 报头,而是创建新的报头。

一个 web 站点可以给一个 web 浏览器发送多个 cookie,一个浏览器也能存储多个 web 站点提供的 cookie(每个站点最多存放 20 个)。一个 cookie(大小限制为 4kb)只能标识一种信息,它至 少含有一个标识该信息的 k -v。

Cookie 的值。如果值为 Unicode 字符,需要为字符编码。如果值为二进制数据,则需要使用 BASE64 编码。

获取 cookie

httpServletRequest.getCookies()
读取所有 cookie 返回数组,遍历通过 cookie.getName()筛选出自己要的(new Cookie()时的第一个参数)。

修改 cookies

如果要修改某个 Cookie,只需要新建一个同名的 Cookie,添加到 response 中覆盖原来的 Cookie。

注意:修改、删除 Cookie 时,新建的 Cookie 除 value、maxAge 之外的所有属性,例如 name、path、domain 等,都要与原 Cookie 完全一样。否则,浏览器将视为两个不同的 Cookie 不予覆盖,导致修改、删除失败。

cookie 属性设置

setMaxAge()

cookie 的时效性:
默认情况下新建的 cookie 是一个会话级别的 cookie(会话 cookie),存储在浏览器内存中,用户关闭浏览器后被删除。

若希望浏览器将该 cookie 存储在磁盘上(持久 cookie),需要使用 maxAge,并给出一个以秒为单位的时间。
如果为负数,该 Cookie 为临时 Cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该 Cookie。这种 cookie 直到超过设定的过期时间才被删除。如果为 0,表示删除该 Cookie。默认为–1。

setPath()

cookie 的作用范围:
默认是当前目录以及子目录,不能作用于上一级目录。
可以自己设置 cookie 的作用范围:
setPath(request.getContextPath)
“/”表示站点的根目录,如果设置为“/”,则本域名下 contextPath 都可以访问该 Cookie。

setDomain()

Cookie 是不可跨域名的。域名 www.google.com 颁发的 Cookie 不会被提交到域名 www.baidu.com 去。这是由 Cookie 的隐私安全机制决定的。隐私安全机制能够禁止网站非法获取其他网站的 Cookie。

正常情况下,同一个一级域名下的两个二级域名如 www.baidu.com 和 images.baidu.com 也不能交互使用 Cookie,因为二者的域名并不严格相同。如果想所有 baidu.com 名下的二级域名都可以使用该 Cookie,需要设置 Cookie 的 domain 参数为.baidu.com。

可以修改本机 hosts 文件来配置多个临时域名来验证 domain 属性。

注意:domain 参数必须以点 (“.”) 开始。另外,name 相同但 domain 不同的两个 Cookie 是两个不同的 Cookie。如果想要两个域名完全不同的网站共有 Cookie,可以生成两个 Cookie,domain 属性分别为两个域名,输出到客户端。

setSecure()

HTTP 协议不仅是无状态的,而且是不安全的。使用 HTTP 协议的数据不经过任何加密就直接在网络上传播,有被截获的可能。使用 HTTP 协议传输很机密的内容是一种隐患。如果不希望 Cookie 在 HTTP 等非安全协议中传输,可以设置 Cookie 的 secure 属性为 true。浏览器只会在 HTTPS 和 SSL 等安全协议中传输此类 Cookie。设置 secure 属性为 true 的代码是 cookie.setSecure(true);

secure 属性并不能对 Cookie 内容加密,因而不能保证绝对的安全性。如果需要高安全性,需要在程序中对 Cookie 内容加密(不可逆加密的)、解密,以防泄密。

其他属性

expires: 失效时间,表示 cookie 何时应该被删除的时间戳(也就是,何时应该停止向服务器发送这个 cookie)。如果不设置这个时间戳,浏览器会在页面关闭时即将删除所有 cookie;不过也可以自己设置删除时间。这个值是 GMT 时间格式,如果客户端和服务器端时间不一致,使用 expires 就会存在偏差。

HttpOnly: 告知浏览器不允许通过脚本 document.cookie 去更改这个值,同样这个值在 document.cookie 中也不可见。但在 http 请求张仍然会携带这个 cookie。注意这个值虽然在脚本中不可获取,但仍然在浏览器安装目录中以文件形式存在。这项设置通常在服务器端设置。

应用场景

自动登入

购物车,最近浏览过的商品

正文完
 0