问题

HTTP协议是一种无状态的协议,Web服务器本身不能识别出哪些请求是同一个浏览器发出的,浏览器的每一次请求都是完全孤立的。
web服务器怎么唯一地标识一个用户,并记录该用户的状态?

会话与状态管理

会话指一个客户端与web服务器之间连续发生的一系列请求和响应过程。(就像把电话拿起到最后挂断)。
会话状态指web服务器与浏览器在会话过程中产生的状态信息,借助会话状态,web服务器把属于同一会话中的一系列请求和响应过程关联起来。

web服务器要从大量的请求消息中区分出哪些请求属于同一会话,即能识别出来自同一个浏览器的访问请求,这需要浏览器对其发出的每个请求消息都进行标识:属于同一个会话中的请求消息都附带同样的标识号,属于不同会话的请求消息附带不同的标识号,这个标识号就称为会话ID。

servlet规范中,有两种机制完成会话跟踪:
cookiesession

cookie

是客户端保持HTTP状态信息的一种方案。
浏览器访问web服务器的某个资源时,由web服务器在HTTP响应消息头中附带传送给浏览器的一个小文本文件(Set-Cookie响应头字段)。如:

Set-Cookie: bid=8UKoeCtJT1M; Expires=Sat, 25-Apr-20 04:02:11 GMT; Domain=.douban.com; Path=/

一旦web浏览器保存了某个cookie,那么它在以后每次访问该web浏览器时都会在HTTP请求头中(Cookie请求头字段)将这个cookie回传给web服务器。如:

Cookie: bid=8UKoeCtJT1M;

如果浏览器不支持Cookie(如大部分手机中的浏览器)或者把Cookie禁用了,Cookie功能就会失效。
不同的浏览器采用不同的方式保存Cookie。
IE浏览器会在C:\Documents and Settings\你的用户名\Cookies文件夹下以文本文件形式保存,一个文本文件保存一个Cookie。

创建cookie

httpServletResponse.addCookie(cookie);
该方法并不修改之前的Set-Cookie报头,而是创建新的报头。

一个web站点可以给一个web浏览器发送多个cookie,一个浏览器也能存储多个web站点提供的cookie(每个站点最多存放20个)。一个cookie(大小限制为4kb)只能标识一种信息,它至 少含有一个标识该信息的k-v。

Cookie的值。如果值为Unicode字符,需要为字符编码。如果值为二进制数据,则需要使用BASE64编码。

获取cookie

httpServletRequest.getCookies()
读取所有cookie返回数组,遍历通过cookie.getName()筛选出自己要的(new Cookie()时的第一个参数)。

修改cookies

如果要修改某个Cookie,只需要新建一个同名的Cookie,添加到response中覆盖原来的Cookie。

注意:修改、删除Cookie时,新建的Cookie除value、maxAge之外的所有属性,例如name、path、domain等,都要与原Cookie完全一样。否则,浏览器将视为两个不同的Cookie不予覆盖,导致修改、删除失败。

cookie属性设置

setMaxAge()

cookie的时效性:
默认情况下新建的cookie是一个会话级别的cookie(会话cookie),存储在浏览器内存中,用户关闭浏览器后被删除。

若希望浏览器将该cookie存储在磁盘上(持久cookie),需要使用maxAge,并给出一个以秒为单位的时间。
如果为负数,该Cookie为临时Cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该Cookie。这种cookie直到超过设定的过期时间才被删除。如果为0,表示删除该Cookie。默认为–1。

setPath()

cookie的作用范围:
默认是当前目录以及子目录,不能作用于上一级目录。
可以自己设置cookie的作用范围:
setPath(request.getContextPath)
“/”表示站点的根目录,如果设置为“/”,则本域名下contextPath都可以访问该Cookie。

setDomain()

Cookie是不可跨域名的。域名www.google.com颁发的Cookie不会被提交到域名www.baidu.com去。这是由Cookie的隐私安全机制决定的。隐私安全机制能够禁止网站非法获取其他网站的Cookie。

正常情况下,同一个一级域名下的两个二级域名如www.baidu.com和images.baidu.com也不能交互使用Cookie,因为二者的域名并不严格相同。如果想所有baidu.com名下的二级域名都可以使用该Cookie,需要设置Cookie的domain参数为.baidu.com。

可以修改本机hosts文件来配置多个临时域名来验证domain属性。

注意:domain参数必须以点(".")开始。另外,name相同但domain不同的两个Cookie是两个不同的Cookie。如果想要两个域名完全不同的网站共有Cookie,可以生成两个Cookie,domain属性分别为两个域名,输出到客户端。

setSecure()

HTTP协议不仅是无状态的,而且是不安全的。使用HTTP协议的数据不经过任何加密就直接在网络上传播,有被截获的可能。使用HTTP协议传输很机密的内容是一种隐患。如果不希望Cookie在HTTP等非安全协议中传输,可以设置Cookie的secure属性为true。浏览器只会在HTTPS和SSL等安全协议中传输此类Cookie。设置secure属性为true的代码是cookie.setSecure(true);

secure属性并不能对Cookie内容加密,因而不能保证绝对的安全性。如果需要高安全性,需要在程序中对Cookie内容加密(不可逆加密的)、解密,以防泄密。

其他属性

expires:失效时间,表示cookie何时应该被删除的时间戳(也就是,何时应该停止向服务器发送这个cookie)。如果不设置这个时间戳,浏览器会在页面关闭时即将删除所有cookie;不过也可以自己设置删除时间。这个值是GMT时间格式,如果客户端和服务器端时间不一致,使用expires就会存在偏差。

HttpOnly: 告知浏览器不允许通过脚本document.cookie去更改这个值,同样这个值在document.cookie中也不可见。但在http请求张仍然会携带这个cookie。注意这个值虽然在脚本中不可获取,但仍然在浏览器安装目录中以文件形式存在。这项设置通常在服务器端设置。

应用场景

自动登入

购物车,最近浏览过的商品


cashew
9 声望3 粉丝

« 上一篇
linux命令
下一篇 »
hadoop梳理