Cookie与Session
1、无状态的Http请求
客户端与服务器之间的请求与响应均是属于HTTP请求,HTTP请求时无状态的,即每一次客户端发起请求时,对于服务端来说均是一次全新的请求,服务器并不知道客户端之前的请求记录。换句话来说当用户登录请求被响应后,就算用户登录成功,用户再次发起其他请求服务器仍不能识别该用户是否登录。
为了解决Http的无状态性,确保客户端与服务器端的会话同步问题。引入了Cookie与Session两个概念。
2、Cookie
在服务器与客户端交互时,会话跟踪是很重要的。理论上来说,个用户的所有请求操作都应该属于同一个会话,而另一个用户的所有请求操作则应该属于另一个会话,二者不能混淆。例如,用户A在超市购买的任何商品都应该放在A的购物车内,不论是用户A什么时间购买的,这都是属于同一个会话的,不能放入用户B或用户C的购物车内,这不属于同一个会话。
但是由于Http的无状态性与无连接性,每次数据交换完毕,服务器与客户端的连接就会关闭,再次交换数据就需要创建新的连接,此时意味着服务器无法连接跟踪上一次的对话。为了能够实现会话的跟踪,Cookie应运而生。
2.1、什么是Cookie?
Cookie,最早由W3C组织提出,是服务器在用户端本地存储的一小段文本信息,服务端的每一次请求都会携带Cookie作为身份的识别,服务器能够通过Cookie跟踪与用户端的会话,这便是Cookie的工作原理。
客户端在请求服务器后,如果需要记录某个用户的状态,只需要使用response
向客户端服务器办法一个Cookie,再次请求该服务器时,浏览器就会把Cookie一同交给服务器,服务器通过检查Cookie来辨别用户状态,例如用户登录状态、用户购物车信息等等。
2.2、Cookie的不可跨域名性
很多网站都会使用Cookie。例如,Google会向客户端颁发Cookie,Baidu也会向客户端颁发Cookie。那浏览器访问Google会不会也携带上Baidu颁发的Cookie呢?或者Google能不能修改Baidu颁发的Cookie呢?
答案是否定的。Cookie具有不可跨域名性。根据Cookie规范,浏览器访问Google只会携带Google的Cookie,而不会携带Baidu的Cookie。Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。
Cookie在客户端是由浏览器来管理的。浏览器能够保证Google只会操作Google的Cookie而不会操作Baidu的Cookie,从而保证用户的隐私安全。浏览器判断一个网站是否能操作另一个网站Cookie的依据是域名。Google与Baidu的域名不一样,因此Google不能操作Baidu的Cookie。
需要注意的是,虽然网站images.google.com与网站www.google.com同属于Google,但是域名不一样,二者同样不能互相操作彼此的Cookie。
2.3、Cookie的属性
Cookie中的内容包括name(名字)、value(值)、maxAge(失效时间)、path(路径),domain(域)和secure
name
:cookie的名字,一旦创建,名称不可更改。
value
:cookie的值,如果值为Unicode字符,需要为字符编码。如果为二进制数据,则需要使用BASE64编码.
maxAge
:cookie失效时间,单位秒。如果为正数,则该cookie在maxAge后失效。如果为负数,该cookie为临时cookie,关闭浏览器即失效, 浏览器也不会以任何形式保存该cookie。如果为0,表示删除该cookie。默认为-1
path
:该cookie的使用路径。如果设置为"/sessionWeb/",则只有ContextPath为“/sessionWeb/”的程序可以访问该cookie。如果设置为“/”,则本域名下ContextPath都可以访问该cookie。
domain
:域.可以访问该Cookie的域名。第一个字符必须为".",如果设置为".google.com",则所有以"google.com结尾的域名都可以访问该cookie",如果不设置,则为所有域名
secure
:该cookie是否仅被使用安全协议传输。
在Java中能够创建Cookie与设置Cookie属性,同时也能够获取客户端传入的Cookie,详细可以参考这篇博客:java对cookie的操作
3、Session
3.1、什么是Session
客户端请求服务端后,服务端为了保存用户状态而开辟一块内存空间,这个内存空间中存储的对象就是Session对象。
Session的目的是为了弥补HTTP无状态的特性,服务器能够利用session存储客户端在同一个会话期间的一些操作记录。
3.2、Session访问机制
当某个客户端访问服务端时,服务端会检查其Cookie中是否有一个标识为sessionID
的Cookie,该Cookie能够作为该客户端在服务端的唯一标识。
如果客户端请求时没有SessionID
这个Cookie,表示为该服务端第一次服务此客户端,服务端会创建一个新的Session并生成一个SessionID
作为此Session的索引,之后通过response为客户端创建sessionID
的Cookie,方便下一次的请求。
如果已经包含了一个SessionID
,标识以前已经为该客户端创建过Session,服务器就按照SessionID
将这个Session索引出来使用。
**注意:**服务器只会在客户端第一次请求响应的时候,在响应头上添加Set-Cookie:“JSESSIONID=XXXXXXX”信息,接下来在同一个会话的第二第三次响应头里,是不会添加Set- Cookie:“JSESSIONID=XXXXXXX”信息的; 而客户端是会在每次请求头的cookie中带上JSESSIONID信息;
4、存在的问题
Cookie存在的缺陷
如果浏览器使用的是cookie,那么所有的数据都保存在浏览器端,但是cookie可以被用户禁止且cookie不安全(对于敏感数据,需要加密),同时cookie只能保存少量的数据(大约是4k),cookie的数量也有限制(大约是几百个)。
Cookie存在多重风险,使用也会非常不便,Cookie的现实使用也有很大的局限性。
Session存在的问题
每一个客户端用户均需要在内存中开辟一块空间存储Session信息,但是如果访问服务器的用户数量越来越多,那么创建的session也会越来越多,影响服务器的负载。如果session内容过于复杂,大量的客户端访问可能导致服务器内存溢出。
同时Session的存在本身就依赖于Cookie,如果浏览器、用户禁止了Cookie的使用,Session也同样无法使用。
由于Cookie与Session的种种缺陷,如今的用户端与服务器端的会话追踪也转而使用token技术,详细可参考其他博客。