目录
Cookie的来历
HTTP协议是诸多互联网应用协议中的一个,不过却是当下最热门的一个互联网应用协议,和它比起来,POP3协议、Telnet协议、FTP协议、Gopher协议已经像是恐龙时代的产物了,基于上述古老协议产生的应用,基本上都已经被基于HTTP协议的应用取代了。和那些古老协议相比,HTTP协议的一个优势是对客户端的应答速度较快。这要得益于它被设计为无连接无状态的协议。所谓无连接无状态,就是执行HTTP协议的Web服务器在处理了客户端的请求之后,立即就关闭了连接,也不保存客户端的访问状态,这就减少了服务器对内存的消耗和网络带宽的占用,相应就提高了服务器的工作效率。
那么该怎样理解这些协议之间的区别呢?举个生活中的列子:
假设有一群顾客到商店里购物,对于POP3、FTP这样的协议来说,它们所安排的售货员为顾客提供一对一服务,直到顾客最终离开商店为止,如果售货员数量不足,其他的顾客就要等待,这将会大大的降低服务器的效率。
而对于HTTP协议,售货员只在顾客需要交互时才出现,三言两语之后就立刻跑去应付另外一个顾客的交互请求,售货员虽然忙一些,但即使很少的售货员也能应付很多的顾客,对于商店来说,工作效率提高了。
但美中不足的是这个售货员是一个脸盲症患者,不管你进进出出超市多少次,他都会把你当做一个新顾客来看待。这和POP3、FTP等协议下的售货员不同,那些售货员都是从头到尾跟着你的,你要是问它:“鸡蛋多少钱一斤?”它回答:“5块钱一斤。”你又向它对话说:“来10斤。”它会回应你:“好嘞,10斤鸡蛋,您拿好了。”但如果是HTTP协议下的售货员,你问它:“鸡蛋多少钱一斤?”它回答:“5块钱一斤。”你又向它对话说:“来10斤。”这时,它满脸茫然的回应你:“你是谁?来什么10斤?”
简而言之,HTTP协议下的服务器根本无法知道两个请求是否来自同一个浏览器
HTTP协议下的售货员要想很好的处理上述情况,就只能在你身上打上特定的标记,例如,你去问售货员:“这鸡蛋多少钱一斤?” 它回答:“5块钱一斤”,同时,它在你身上贴张纸条“此人要买鸡蛋”,这样当你跟售货员说“来10斤”时,它听到你说话的同时,又看到你身上这个“此人要买鸡蛋”的纸条,自然就会明白你要买10斤什么,也就能正确地给你提供服务了。
回过头来讲,由于HTTP是无状态的协议,一旦客户端和服务器的数据交换完毕,就会断开连接,再次请求,会重新连接,这就说明服务器单从网络连接上是没有办法知道用户身份的。怎么办呢?那就给每次新的用户请求时,给它贴上一个标签(独一无二)吧,下次访问时,这样服务器就会知道是谁来访问了,针对不同用户,做出不同的响应。
与上面的例子类似,在web设计领域要服务器要想判断是否为同一用户一般会有三种做标记的方法:
1.在返回给客户端的页面中加入一些隐藏信息,这些信息会在用户点击页面中按钮进行提交时发送到服务器上;
2.在返回给客户端的页面的链接地址中加入一些信息,点击这些链接时就把这些信息回传到服务器上了;
3.以上两种方式都有缺陷之处,所以选择Cookie技术无疑是最佳解决方案
cookie的诞生:
网景公司当时一名员工Lou Montulli,在1994年将“cookies”的概念应用于网络通信,用来解决用户网上购物的购物车历史记录,目前所有浏览器都支持cookies。
cookie是什么?
cookie其实是一段很小的文本,是储存在浏览器内存中或者是储存在用户的计算机硬盘中的,储存一些服务器需要的信息,每次浏览器访问指定的服务器时,都会把cookie的信息再次带回到服务器中。
在了解cookie之前我们先来看看什么是会话?
所谓的一次会话就是:浏览器开始访问某一服务器,直到关闭浏览器,对此服务器停止访问,在此期间产生的所有请求与相应加在一起称之为一次会话。
Cookie的基本API与工作原理
1. 浏览器发送请求至服务器,服务器收到请求,并获取请求中携带的数据
//获取用户的数据值
String value = request.getParameter("参数名");
2. 此时服务器会创建cookie对象,并将这些数据保存到cookie中
Cookie cookie = new Cookie("name",value);//创建一个cookie对象
cookie.setMaxAge(60*60*24);//设置生存时间
response.addCookie(cookie);//将cookie添加到响应中
3. 之后,通过set-Cookie(name=value)响应头发送给浏览器,让浏览器保存
4. 浏览器每次访问指定的服务器时,都会通过Cookie请求头将数据带回服务器
Cookie[] cs = request.getCookies(); //获取所有cookie
5. 并没有直接销毁cookie的API,但是我们可以通过setMaxAge()方法,设置生命时常间接销毁cookie,但必须和想要删除的cookie的名字一致。
Cookie ck = new Cookie("name","");
ck.setMaxAge(0);
response.addCookie(ck);
6.获取cookie的名字(cookie的key值)
cookie.getName()
7.获取cookie中的属性值
cookie.getValue()
8.设置cookie中保存的值
cookie.setValue()
大体示例:
/**
* 用户登录
* @return
* cookie
* 默认条件下,cookie只会记录当前网址信息
* 由于业务的需要,如果cookie需要共享数据时
* 则必须设置domain属性
*/
@RequestMapping("doLogin")
@ResponseBody
public SysResult doLogin(User user,HttpServletResponse response) {
String uuid=dubboUserService.findUserInfo(user);
//登录失败
if(StringUtils.isEmpty(uuid)) {
return SysResult.fail();
}
//创建cookie
Cookie cookie=new Cookie("JT_TICKET", uuid);
//设置生命周期
cookie.setMaxAge(7*24*60*60-1);
//设置cookie域以及httpOnly属性
cookie.setDomain("jt.com");
cookie.setPath("/");
//不能通过document.cookie获取,保证安全性
cookie.setHttpOnly(true);
//发送cookie
response.addCookie(cookie);
//登录成功
return SysResult.success();
}
各浏览器中对cookie的限制个数:

如果cookie的数量超出了限制会如何?
如果cookie的数量超过了浏览器的限制,浏览器将会剔除一些之前保存的cookie,不同的浏览器机制也不一样,IE浏览器是通过LRU算法将一些搁置已久的cookie清除,而Firefox的机制是随机剔除某些cookie的值。
Cookie的类型:会话Cookie与持久Cookie:
默认是会话级别的cookie,此时cookie是存储在浏览器的内存中,即当用户关闭浏览器后,cookie也就消亡了。
如果设置一个特定的过期时间(Expires)或者有效期(Max-Age)
cookie.setMaxAge()方法,设置了生命周期,cookie会被储存在硬盘中,只要在此cookie生命周期内,访问特定的服务器,便可以发送cookie。
以下是Cookie的基本格式及属性
Set-Cookie:cookiename=cookievalue;expire=过期时间;path=url路径;domain=域名
我们在以上的语句中看到了许多有关cookie的属性:其中,cookie的名字是cookiename对应一个cookievalue,也就是cookie的值,它们之间使用=连接;expire属性是用来给此cookie设置一个过期时间的,一旦到达了指定的时间cookie也就消亡了(也可以使用setMaxAge设置生命周期);path对应一个url地址;domain对应的是一个域名。以上,除第一个是必选项其他的可选。
expire属性:
Expires=Wed, 21 Oct 2019 07:28:00 GMT;
path属性:
此属性可以填写一个路径名,比如域名是:domain="taobao.com",path属性是:path="/page"
那么只有访问域名为taobao.com中路径是page的页面才会读取到cookie
taobao.com/page
如果访问的是taobao.com域名下的index网页cookie不会被读取。
taobao.com/index
一般path路径设置成 / 如果在项目中不设置path路径,浏览器将收不到cookie
cookie.setPath("/");
domain属性:
产生Cookie的服务器可以向set-Cookie响应首部添加一个Domain属性来控制哪些站点可以看到那个cookie,用户只有在访问www.baidu.com的时候,才会发送这个cookie。
Set-Cookie: name="李逵"; domain="www.baidu.com"
在服务器端如果想要设置domain属性可以使用:
cookie.setDomain("jd.com")
此外还有一些属性:
secure属性:
设置了属性secure,cookie只有在https协议加密情况下才会发送给服务端。但是这并不是最安全的,由于其固有的不安全性,敏感信息也是不应该通过cookie传输的.
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure;
HttpOnly属性:
若此属性为true,则只有在http请求头中会带有此cookie的信息,而不能通过document.cookie来访问此cookie。HttpOnly属性可以保证用户cookie的安全性,有效的防止了XSS攻击(跨站脚本攻击),通过js脚本也无法读取到cookie的信息,在此只做简单介绍,想了解更多内容可以阅读以下博客。
如果感兴趣可以阅读以下博客
什么是xss攻击?
https://blog.youkuaiyun.com/qq_27552077/article/details/61671671
SameSite属性:
从Chrome 51开始,浏览器的 Cookie 新增加了一个SameSite属性,用来防止 CSRF 攻击和用户追踪,它是谷歌开发的一种安全机制,在此只做简单介绍,想了解更多内容可以阅读以下博客。
如果感兴趣可以阅读以下博客
http://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html
https://blog.youkuaiyun.com/yanyang1116/article/details/56511009
下面是chrome(谷歌)浏览器的cookie展示: 
了解完基本属性之后我们再来回顾一下cookie的工作过程
你在浏览器的地址栏输入了某一web资源的URL,浏览器就会向这个URL的web站点发送请求,比如:www.shimo.com ,当你点击回车发送请求后,此服务器就能获取到你计算机中域名(也就是之前提到过的domain属性)与www.shimo.com相同的cookie,浏览器就会把相关的Cookie“键=值”的数据跟请求一起发送到服务器,如果不存在域名是www.shimo.com的cookie,则浏览器不发送任何Cookie。如果 www.shimo.com
没有获取到cookie,它就会得知你以前并没有访问过此网站,它就会分配一个新用户的ID,并在把你所请求的页面发回到你的浏览器时,把用户ID“键=值”也发送到你的计
算机上,你的硬盘就会驻留了对应这个站点的“键=值”(Cookie)
对于站点来讲,能够精确的知道有多少访问者在实际的访问站点,它能排除哪些因为代理服务器,缓冲器,集中器等等带来的干扰,正确统计站点访问数的唯一方法是为每一个来访者设置一个唯一的ID,并存在Cookie中,用Cookie,站点能够得知有多少访问者, 得知此用户是新用户还是老用户,也可以确定一个用户访问的频度次数是多少。
Java Script中的cookie:
通过document可以获取此浏览器中的cookie
var cookies=document.cookie;
console.log(cookies);
也可以设置cookie,格式是键值对形式
document.cookie="name=linchong";
console.log(document.cookie);
上面提到的HttpOnly属性,可以禁止javascript操作cookie,也就是说通过javascript的document.cookie无法访问带有HttpOnly标记的cookie(为避免跨域脚本(xss)攻击)
Set-Cookie: id=b2a1; Expires=Wed, 21 Oct 2017 07:28:00 GMT; Secure; HttpOnly
有关cookie还有一个概念
第三方cookie
什么是第三方cookie?
上面的章节我们提到了cookie中的domain属性,不知大家还有没有印象呢,一般情况下,我们去访问网站 www.aaa.com 在访问后此网站给你的浏览器发送了一个cookie,其中cookie的domain属性也是aaa.com,与你访问的域名相同,它归属于www.aaa.com,这就是第一方cookie。而如果当你访问www.aaa.com 的时候,发送到你浏览器中的cookie的domain属性是bbb.com,这个cookie归属于bbb.com所有,cookie的域名与你访问的网站域名不一致,这是第三方cookie。
所以,第一方Cookie并不一定需要由某个网站自己的服务器给自己建立,别的网站也能为它建立,它也能去建立别的网站的cookie;而且,第一方Cookie也不一定是能由某个网站自己读取的,它完全可能由第三方读取。
想了解小伙伴可以去百度看一哈~~
1102

被折叠的 条评论
为什么被折叠?



