前言
HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据。浏览器会存储 cookie 并在下次向同一服务器再发起请求时携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器——如保持用户的登录状态。Cookie 使基于无状态的 HTTP 协议记录稳定的状态信息成为了可能。
cookie的作用
-
会话状态管理 如用户登录状态、购物车、游戏分数或其它需要记录的信息
-
个性化设置 如用户自定义设置、主题和其他设置
-
浏览器行为跟踪 如跟踪分析用户行为等
Cookie 曾一度用于客户端数据的存储,因当时并没有其它合适的存储办法而作为唯一的存储手段,但现在推荐使用现代存储 API。由于服务器指定 Cookie 后,浏览器的每次请求都会携带 Cookie 数据,会带来额外的性能开销(尤其是在移动环境下)。新的浏览器 API 已经允许开发者直接将数据存储到本地,如使用 Web storage API(
localStorage
和sessionStorage
)或 IndexedDB
cookie的创建
cookie创建有两种方式:
- 最常见的设置方式是接口调用时,由服务端人员配置Set-Cookie的方式实现,调用该接口后,cookie会自动写入到浏览器,但是写入的成功与否需要取决于damain的参数的配置,这个放到后面会说。如果只是简单的设置cookie的name和value,是肯定不会有问题的。
Set-Cookie: <cookie-name>=<cookie-value>
- 前端可以通过js脚本实现添加cookie
document.cookie = 'xx=xxx'
- 还有就是可以通过控制台的application,找到里边的cookie,然后手动往当前域新增(但这种方式只局限于开发环境做测试使用)
cookie的使用
cookie的携带属于浏览器的默认行为,当然我们也可以通过设置去禁用cookie的使用,但是这样可能会导致有些网站无法正常的使用。cookie的携带其实只要满足了浏览器期待的几个条件,在进行接口调用的时候,就会自动将其携带上,这样其实有利有弊的,好处是只要设置了cookie并且满足cookie的作用域,接口就会自动携带,减少了代码量并且实现了用户认证。缺点是只要满足了作用域的所有接口,都会携带上cookie信息。所以其实cookie的使用也要看场景是否合适再做决定。
服务端设置了cookie后,前端人员如果想要通过js脚本代码去获取对应值,有一个前置条件,那就是httponly,只有服务端没设置这个值,前端才能通过js脚本取得该值。
参数详解
Domain
表示的cookie的作用域,即只有该域名下才能存储接口,也只有该域名的接口可以携带cookie信息。如果未设置该值则默认为同一host下可以使用。这个地方可以设置顶级域名,这样该域名下对应站点和接口可以使用,也可以设置完整域名,这样则有更严格的使用标准。这个取决于使用者希望哪些场景能使用和携带这个cookie值。
path
和Domain共同组成作用域信息,即对应路径的接口可以携带cookie信息,默认是'/',即所有子路径都可以访问
Expires/Max-Age
表示cookie的有效期,如果是会话级别则会在浏览器关闭窗口时自动销毁;如果是一个日期或者max-age则会在到期后销毁;
HttpOnly
表示是否只有http和https协议能够访问该cookie,如果设置了值为true,则不能通过js脚本取得cookie值
Secure
标记为 Secure
的 Cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端。它永远不会使用不安全的 HTTP 发送(本地主机除外),这意味着中间人攻击者无法轻松访问它。不安全的站点(在 URL 中带有 http:
)无法使用 Secure
属性设置 cookie。但是,Secure
不会阻止对 cookie 中敏感信息的访问。例如,有权访问客户端硬盘(或,如果未设置 HttpOnly
属性,则为 JavaScript)的人可以读取和修改它
SameSite
SameSite
属性允许服务器指定是否/何时通过跨站点请求发送(其中站点 (en-US)由注册的域和方案定义:http 或 https)。这提供了一些针对跨站点请求伪造攻击(CSRF)的保护。它采用三个可能的值:Strict
、Lax
和 None
使用 Strict
,cookie 仅发送到它来源的站点。
Lax
与 Strict 相似,只是在用户导航到 cookie 的源站点时发送 cookie。例如,通过跟踪来自外部站点的链接。None
指定浏览器会在同站请求和跨站请求下继续发送 cookie,但仅在安全的上下文中(即,如果 SameSite=None
,且还必须设置 Secure
属性)如果没有设置 SameSite
属性,则将 cookie 视为 Lax
.
- 如果
SameSite
未指定,则SameSite=Lax
时新的默认值。以前,默认情况下会为有请求发送 cookie。SameSite=None
的 cookie 还必须指定Secure
属性(它们需要安全上下文)。- cookie 使用不同的方案(
http:
或https:
)发送来自同一域的 cookie,则不再视为来自同一站点。
cookie涉及的安全
缓解涉及 Cookie 的攻击的方法:
- 使用
HttpOnly
属性可防止通过 JavaScript 访问 cookie 值。 - 用于敏感信息(例如指示身份验证)的 Cookie 的生存期应较短,并且
SameSite
属性设置为Strict
或Lax
。(请参见上方的 SameSite Cookie。)在支持 SameSite 的浏览器中,这样做的作用是确保不与跨域请求一起发送身份验证 cookie。因此,这种请求实际上不会向应用服务器进行身份验证。
cookie本地开发遇到的问题
看了前面的介绍我们可以知道,如果在调试过程中,前端的接口域名如果和接口域名不一致,这个cookie就不能正常携带,就会导致开发过程不方便调试。线上环境其实只要保证前端域名和接口域名和cookie配置的Domain和path匹配,基本都能正常。
那我们本地开发如果解决这种cookie没有携带的问题呢?方法也很简单,我们只需要配置一个接口代理就行了,这样前端域名和接口都是你的localhost。
如有觉得不对的地方,也欢迎大家进行交流!