状态管理介绍
为什么需要状态管理
- HTTP协议是无状态的,不能保存每次提交的信息,即当服务器返回与请求相对应的应答之后,这次事务的所有信息就丢掉了。
- 如果用户发来一个新的请求,服务器无法知道它是否与上次的请求有联系。
- 对于那些需要多次提交数据才能完成的Web操作,比如登录来说,就成问题了。
什么是状态管理
- WEB应用中的
会话
是指一个客户端浏览器与WEB服务器之间连续发生的一系列请求和响应过程。- WEB应用的
会话状态
是指WEB服务器与浏览器在会话过程中产生的状态信息,借助会话状态,WEB服务器能够把属于同一会话中的一系列的请求和响应过程关联起来。
状态管理的两种常见模式
- 客户端状态管理技术:将状态保存在客户端。代表性的是
Cookie技术
。- 服务器状态管理技术:将状态保存在服务器端。代表性的是
session技术
(服务器传递sessionID时需要使用Cookie的方式)和application
Cookie简介
什么是Cookie
- Cookie是在浏览器访问WEB服务器的某个资源时,由WEB服务器在HTTP响应消息头中附带传送给浏览器的一小段数据,WEB服务器传送给各个客户端浏览器的数据是可以各不相同的。
- 一旦WEB浏览器保存了某个Cookie,那么它在以后每次访问该WEB服务器时,都应在HTTP请求头中将这个Cookie回传给WEB服务器。
- WEB服务器通过在HTTP响应消息中增加Set-Cookie响应头字段将Cookie信息发送给浏览器,浏览器则通过在HTTP请求消息中增加Cookie请求头字段将Cookie回传给WEB服务器。
- 一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。
- 一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie。
- 浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB
- Servlet 2.5 API 不支持 cookie设置HttpOnly,建议升级Tomcat7.0,它已经实现了Servlet3.0。两种方式可以设置
Cookie的使用
创建Cookie
- 代码示例:
//第一个参数是存储cookie的名字,第二个参数是cookie中需要保存的值 Cookie cookie=new Cookie("code", code); cookie.setPath("/");//设置Cookie的路径 cookie.setMaxAge(-1);//内存存储,取值有三种:>0有效期,单位秒;=0失效;<0内存存储,默认-1 //将cookie设置成HttpOnly是为了防止XSS攻击,窃取cookie内容,这样就增加了cookie的安全性,即便是这样,也不要将重要信息存入cookie。 cookie.setHttpOnly(true); response.addCookie(cookie);//让浏览器添加Cookie //注意:有效路径: 当前访问资源的上一级目录,不带主机名
- 介绍另外一种办法:
- 利用HttpResponse的addHeader方法,设置Set-Cookie的值
- cookie字符串的格式:key=value; Expires=date; Path=path; Domain=domain; Secure; HttpOnly
- //设置cookie
- response.addHeader(“Set-Cookie”, “uid=112; Path=/; HttpOnly”);
- //设置多个cookie
- response.addHeader(“Set-Cookie”, “uid=112; Path=/; HttpOnly”);
- response.addHeader(“Set-Cookie”, “timeout=30; Path=/test; HttpOnly”);
- //设置https的cookie
- response.addHeader(“Set-Cookie”, “uid=112; Path=/; Secure; HttpOnly”);
- 在实际使用中,我们可以使FireCookie查看我们设置的Cookie 是否是HttpOnly
查询Cookie
- 代码示例:
//获取所有的Cookie Cookie[] cks=request.getCookies(); //遍历Cookie for(Cookie ck:cks){ //检索出自己的Cookie if(ck.getName().equals("code")){ //记录Cookie的值 code=ck.getValue(); break; } }
修改Cookie
- 执行上边的创建Cookie代码,只需要保证Cookie的名和路径一致即可修改
- 注意:如果改变
cookie的name
和有效路径
会新建cookie, 而改变cookie值、有效期、和httponly会覆盖原有cookie
删除Cookie
- 保证Cookie的名和路径一致,然后传入空值,设置时间为0,表示立即过时
- 代码示例:
Cookie cookie = new Cookie("cood",""); cookie.setPath("/"); cookie.setMaxAge(0); response.addCookie(cookie);
Cookie详解
Cookie的生存时间
- ck.setMaxAge(-1);设置生成时间,默认-1
- 取值说明:
- >0 有效期,单位秒
- =0 失效
- <0 内存存储
Cookie的编码与解码
- 中文和英文字符不同,中文属于Unicode字符,在内存中占用4个字符,而英文属于ASCII字符,内存中只占2个字节。Cookie中使用Unicode字符时需要对Unicode字符进行编码,否则会出现乱码。
- 编码可以使用java.net.URLEncoder类的encode(String str,String encoding)方法
- 解码使用java.net.URLDecoder类的decode(String str,String encoding)方法
- 保存代码示例:
// 使用中文的 Cookie. name 与 value 都使用 UTF-8 编码. Cookie cookie = new Cookie(URLEncoder.encode("姓名", "UTF-8"), URLEncoder.encode("老邢", "UTF-8")); // 发送到客户端 response.addCookie(cookie);
- 读取代码示例:
if(request.getCookies() != null){ for(Cookie cc : request.getCookies()){ String cookieName = URLDecoder.decode(cc.getName(), "UTF-8"); String cookieValue = URLDecoder.decode(cc.getValue(), "UTF-8"); out.println(cookieName + "="); out.println(cookieValue + "; <br/>"); } }else{ out.println("Cookie 已经写入客户端. 请刷新页面. "); }
Cookie的路径问题
- cookie 一般都是由于用户访问页面而被创建的,可是并不是只有在创建 cookie 的页面才可以访问这个cookie。
- 在默认情况下,出于安全方面的考虑,只有与创建 cookie 的页面处于同一个目录或在创建cookie页面的子目录下的网页才可以访问。
- 那么此时如果希望其父级或者整个网页都能够使用cookie,就需要进行路径的设置。
发送Cookie的条件
- 浏览器在发送请求之前,首先会根据请求url中的域名在cookie列表中找所有与当前域名一样的cookie,然后再根据指定的路径进行匹配,如果当前请求在域匹配的基础上还与路径匹配那么就会将所有匹配的cookie发送给服务器。
设置Cookie的路径
- 通过Cookie的setPath方法设置路径
- cookie.setPath(“/”);
Cookie的特点
优点:
- 可配置到期规则:Cookie 可以在浏览器会话结束时到期,或者可以在客户端计算机上无限期存在,这取决于客户端的到期规则,不需要任何服务器资源,Cookie 存储在客户端并在发送后由服务器读取。
- 简单性:Cookie 是一种基于文本的轻量结构,包含简单的键值对。
- 数据持久性:虽然客户端计算机上 Cookie 的持续时间取决于客户端上的 Cookie 过期处理和用户干预,Cookie 通常是客户端上持续时间最长的数据保留形式
缺点:
- 大小受到限制:大多数浏览器对 Cookie 的大小有 4096 字节的限制,尽管在当今新的浏览器和客户端设备版本中,支持 8192 字节的 Cookie 大小已愈发常见。
- 用户配置为禁用:有些用户禁用了浏览器或客户端设备接收 Cookie 的能力,因此限制了这一功能。
- 潜在的安全风险:Cookie 可能会被篡改。用户可能会操纵其计算机上的 Cookie,这意味着会对安全性造成潜在风险或者导致依赖于Cookie 的应用程序失败。
参考
- 部分参考来自lay500