Cookie和Session你不能不知道的秘密
1、cookie是什么
由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。如下图:
1.1、cookie的属性
属性项 | 属性项介绍 |
---|---|
Name | 一个唯一确定cookie的名称(cookie名称不区分大小写,实践中最好区分,因为一些服务器会区分),URL编码 |
Value | 存储cookie的字符串值,值必须经过URL编码 |
Expires | 过期时间,在这个时间点后Cookie失效 |
Domain | 生成Cookie域名 |
Path | 该Cookie是在当前那个路径下生成的 |
Secure | 加密设置,设置他之后,只会在SSL连接时才会回传该Cookie |
这里我只要说二个点:
1、Expires:该Cookie失效的时间,单位秒。
- 如果为正数,则该Cookie在maxAge秒之后失效(持久级别Cookie)。
- 如果为负数,该Cookie为临时Cookie,关闭浏览器即失效(会话级别Cookie),浏览器也不会以任何形式保存该Cookie。
- 如果为0,表示删除该Cookie。默认为–1;
2、Domain:
我们现在有二个域名。域名A:b.f.com,域名B:d.f.com;显然域名A和域名B都是f.com的子域名
- 如果我们在域名A中的Cookie的domain设置为.f.com,那么.f.com及其子域名都可以获取这个Cookie,即域名A和域名B都可以获取这个Cookie
如果域名A没有显式设置Cookie的domain方法,那么domain就为.b.f.com,不一样的是,这时,域名A的子域名将无法获取这个Cookie
HttpOnly: 这个属性是面试的时候常考的,如果这个属性设置为true,就不能通过js脚本来获取cookie的值,能有效的防止xss攻击
1.2、cookie的操作
由于js没有给原生的操作方法,我们可以简单地封装一下:
var cookieUtil = { getItem: function (name) { var cookieName = encodeURIComponent(name) + "=", cookieStart = document.cookie.indexOf(cookieName), cookieValue = null; if (cookieStart > -1) { var cookieEnd = document.cookie.indexOf(';', cookieStart); if (cookieEnd == 1) { cookieEnd = document.cookie.length; } cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd)) } return cookieValue; }, setItem: function (name, value, expires, path, domain, secure) { var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value); if (expires) { cookieText += ";expires=" + expires.toGMTString(); } if (path) { cookieText += ";path=" + path; } if (domain) { cookieText += ";domain=" + domain; } if (secure) { cookieText += ";secure"; } document.cookie = cookieText; }, unset: function (name, path, domain, secure) { this.setItem(name, "", new Date(0), path, domain, secure) } } CookieUtil.setItem("name", 'tom'); // 设置cookie console.log(CookieUtil.getItem('name'));//读取cookie CookieUtil.unset("name")//删除cookie
1.3、Cookie防篡改机制
因为Cookie是存储在客户端,用户可以随意修改。所以,存在一定的安全隐患。
防篡改签名:服务器为每个Cookie项生成签名。如果用户篡改Cookie,则与签名无法对应上。以此,来判断数据是否被篡改。
原理如下:
- 服务端提供一个签名生成算法secret
- 根据方法生成签名secret(wall)=34Yult8i
- 将生成的签名放入对应的Cookie项username=wall|34Yult8i。其中,内容和签名用|隔开。
- 服务端根据接收到的内容和签名,校验内容是否被篡改。
举个栗子:
比如服务器接收到请求中的Cookie项username=pony|34Yult8i,然后使用签名生成算法secret(pony)=666。 算法得到的签名666和请求中数据的签名不一致,则证明数据被篡改。
2、Session
Session: 是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中.为了获得更高的存取速度,服务器一般把Session放在内存里。每个用户都会有一个独立的Session。如果Session内容过于复杂,当大量客户访问服务器时可能会导致内存溢出。因此,Session里的信息应该尽量精简。
当客户端请求创建一个session的时候,服务器会先检查这个客户端的请求里是否已包含了一个session标识 - sessionId,
- 如果已包含这个sessionId,则说明以前已经为此客户端创建过session,服务器就按照sessionId把这个session检索出来使用(如果检索不到,可能会新建一个)
- 如果客户端请求(一般是通过cookie携带)不包含sessionId,则为此客户端创建一个session并且生成一个与此session相关联的sessionId
sessionId的值一般是一个既不会重复,又不容易被仿造的字符串,这个sessionId将被在本次响应中返回给客户端保存。保存sessionId的方式大多情况下用的是cookie。
session 的运行依赖 session id,而 session id 是存在 cookie中的
如果客户端的浏览器禁用了 Cookie怎么办?一般这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,(在 url 中传递 session_id)即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。
3、cookie与session的区别
cookie | session | |
---|---|---|
存储位置 | 客户端 | 服务器端 |
存取方式 | 只能保管ASCII字符串 | 够存取任何类型的数据 |
有效期不同 | Cookie可以设置过期时间属性 | JSESSIONID的过期时间默许为–1,只需关闭了阅读器该Session就会失效 |
服务器压力 | Cookie保管在客户端,不占用服务器资源。假如并发阅读的用户十分多,Cookie是很好的选择 | Session是保管在服务器端的,每个用户都会产生一个Session。假如并发访问的用户十分多,会产生十分多的Session,耗费大量的内存 |
跨域支持上的不同 | Cookie支持跨域名访问,例如将domain属性设置为“.biaodianfu.com”,则以“.biaodianfu.com”为后缀的一切域名均能够访问该Cookie。 | Session则不会支持跨域名访问。Session仅在他所在的域名内有效。 |
区分路径 | cookie中如果设置了路径参数,那么同一个网站中不同路径下的cookie互相是访问不到的 | session不能区分路径,同一个用户在访问一个网站期间,所有的session在任何一个地方都可以访问到 |
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎star对作者也是一种鼓励。