常用的会话跟踪技术Cookie与Session。
会话跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。
Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。
一.cookie
Cookie实际上是一小段的文本信息。
客户端向服务器发起请求,若服务器需要记录该用户状态,Cookie的处理:
- 服务器使用response向客户端发送cookie
- 浏览器将cookie保存
- 之后每次http请求浏览器都会将cookie发送给服务器端。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。
服务器端的发送与解析
发送cookie
服务器端向客户端发送Cookie是通过HTTP响应报文实现的,在Set-Cookie中设置需要向客户端发送的cookie,格式如下:
Set-Cookie: "name=value;domain=.domain.com;path=/;expires=Sat, 11 Jun 2016 11:29:42 GMT;HttpOnly;secure"
其中name=value是必选项,其它都是可选项。
Cookie的主要构成如下:
name:唯一确定的cookie名称。不区分大小写。 Name 和 Value 属性由程序设定,默认值都是空引用。
value:存储在cookie中的字符串值。最好为cookie的name和value进行url编码
domain(域):cookie对哪个域有效。Domain属性的默认值为当前URL的域名部分。所有向该域发送的请求中都会包含这个cookie信息。这个值可以包含子域(如:
yq.aliyun.com),也可以不包含它(如:.aliyun.com,则对于aliyun.com的所有子域都有效).
http://www.baidu.com/xxx/login.aspx 页面中发出一个cookie,Domain属性缺省就是www.baidu.com ,
可以由程序设置此属性为需要的值。
若值是域名,比如www.china.com。这是对path路径属性的一个延伸。
如果我们想让 www.china.com能够访问bbs.china.com设置的cookies,该怎么办?
把domain属性设置成“china.com”, 并把path属性设置成“/”。
path: 表示这个cookie影响到的路径,浏览器跟会根据这项配置,向指定域中匹配的路径发送cookie。Path属性的默认值是根目录,即 ”/”
如果http://www.china.com/test/index.html 建立了一个cookie,那么在http://www.china.com/test/目录里的所有页面,
以及该目录下面任何子目录里的页面都可以访问这个cookie.
如果http://www.china.com/test/ 需要访问http://www.china.com/test/index.html设置的cookes,该怎么办?
把cookies的path属性设置成“/”。在指定路径的时候,凡是来自同一服务器,URL里有相同路径
的所有WEB页面都可以共享cookies。
expires:失效时间,表示cookie何时应该被删除的时间戳(也就是,何时应该停止向服务器发送这个cookie)。如果不设置这个时间戳,浏览器会在页面关闭时即将删除所有cookie;不过也可以自己设置删除时间。这个值是GMT时间格式,如果客户端和服务器端时间不一致,使用expires就会存在偏差。
max-age: 与expires作用相同,用来告诉浏览器此cookie多久过期(单位是秒)。max-age的优先级高于expires。
HttpOnly: 告知浏览器不允许通过脚本document.cookie去更改这个值,同样这个值在document.cookie中也不可见。但在http请求张仍然会携带这个cookie。注意这个值虽然在脚本中不可获取,但仍然在浏览器安装目录中以文件形式存在。这项设置通常在服务器端设置。
secure: 安全标志,指定后,只有在使用SSL链接时候才能发送到服务器,如果是http链接则不会传递该信息。就算设置了secure 属性也并不代表他人不能看到你机器本地保存的 cookie 信息,所以不要把重要信息放cookie就对了服务器端设置
cookie示例如下:
1.直接设置cookie
1 2 3 4 5 6 7 8 9 |
|
2.封装对cookie的设置(直接设置Set-Cookie过于原始,可以对cookie的设置过程做如下封装)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
注意: | 如果给cookie设置一个过去的时间,浏览器会立即删除该cookie; domain项必须有两个点(.),因此localhost是无效的,浏览器将拒绝设置cookie! |
服务器端解析cookie
cookie可以设置不同的域与路径,同一个name value可用于不同域不同路径下,浏览器会按照与当前请求url或页面地址最佳匹配的顺序来排定先后顺序
所以当前端传递到服务器端的cookie有多个重复name value时,我们只需要最匹配的那个,也就是第一个。
服务器端解析代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
客户端的存取
浏览器将后台传递过来的cookie进行管理,并且允许开发者在JavaScript中使用document.cookie来存取cookie。
当用来时,返回当前页面可用的(根据,字符串的格式如下:
document.cookie 获取cookie的域、路径、失效时间和安全设置(字符串)
1 |
|
document.cookie=" " 设置一个新的cookie字符串。 这个字符串会被解释并添加到现有的cookie集合中
1 |
|
设置document.cookie并不会覆盖cookie,除非设置的name value domain path都与一个已存在cookie重复。
针对cookie的添加、修改、删除。封装函数来处理cookie
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
|
会话Cookie和持久Cookie
会话cookie:若不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失。。会话cookie一般不存储在硬盘上而是保存在内存里。
持久Cookie:若设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie仍然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在浏览器的不同进程间共享。
Cookie具有不可跨域名性 也就是说:浏览器访问百度不会带上谷歌的cookie。
二. Session
Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
每个用户访问服务器都会建立一个session,那服务器是怎么标识用户的唯一身份呢?
用户与服务器建立连接的同时,服务器会自动为其分配一个SessionId。
1、两个问题:
1)什么东西可以让你每次请求都把SessionId自动带到服务器呢?
显然就是cookie了,如果你想为用户建立一次会话,可以在用户授权成功时给他一个唯一的cookie。当一个用户提交了表单时,浏览器会将用户的SessionId自动附加在HTTP头中(这是浏览器的自动功能),当服务器处理完这个表单后,将结果返回给SessionId所对应的用户。
2)储存需要的信息。服务器通过SessionId作为key,读写到对应的value,这就达到了保持会话信息的目的。
2、session的创建:
当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了sessionId,如果已包含则说明以前已经为此客户端创建过session,服务器就按照sessionId把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含sessionId,则为此客户端创建一个session并且生成一个与此session相关联的sessionId,sessionId的值是一个既不会重复,又不容易被找到规律以仿造的字符串,这个sessionId将被在本次响应中返回给客户端保存。
3、禁用cookie:
如果客户端禁用了cookie,通常有两种方法不依赖cookie实现session。
1)URL重写,就是把sessionId直接附加在URL路径的后面。
2)表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。比如:
<form name="testform" action="/xxx">
<input type="hidden" name="sessionid" value="hhjjuubzWoWiBYEnLerjQ99zWpBng!-145788764">
<input type="text">
</form>
4、Session共享:
对于多网站(同一父域不同子域)单服务器,我们需要解决的就是来自不同网站之间SessionId的共享。
由于域名不同(aaa.test.com和bbb.test.com),而SessionId又分别储存在各自的cookie中,因此服务器会认为对于两个子站的访问,是来自不同的会话。
解决的方法:修改cookies的域名为父域名达到cookie共享的目的,从而实现SessionId的共享。带来的弊端就是,子站间的cookie信息也同时被共享了。