Cookie和Session

Web应用中的会话及会话管理

  • HTTP协议是一个无状态的的协议,当一个客户端向服务器发出请求,在服务器返回响应后,连接就关闭了。这时,在服务器端不保留连接的相关信息,因此当下一次请求连接时,服务器已没有以前的连接信息了,也就无法判断这一次连接和以前的连接是否属于同一客户,也就是说Web服务器无法跟踪客户状态。
  • 在Servlet规范中,常用以下两种机制完成会话跟踪
    1.使用持续的Cookie
    2.使用Servlet API中Session(会话)机制

Cookie

什么是Cookie

  • Cookie是一种在客户端保持HTTP状态信息的技术
  • Cookie是在浏览器访问Web服务器端的某个资源时,由WEB服务器在HTTP应答头中附带传送给浏览器的一个数据,WEB服务器传送给客户端浏览器的数据可以是各不相同的;
  • 一旦浏览器保存了某个Cookie,那么它以后每次访问服务端时,Cookie都应附加在请求头中传回给服务器
  • 一个Cookie只能记录一种信息,它至少含有一个标识信息的名称(NAME)和设置值(VALUE)(k-v);
  • 一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个站点所提供的Cookie;
  • 浏览器一般最多能存入300个Cookie,每个站点最多可以存放20个Cookie,每个Cookie大小限制在4kb
  • Cookie只能送回给创建它的服务器,不可以送到其他的服务器;
  • Cookie的基本工作原理“
客户计算机                              服务器
           1.客户端请求                 
           2.服务器在响应头中设置Cookies  
 Cookies   3.客户端再次请求文档           
           4.服务器读取Cookies           

创建Cookie

  • 创建Cookie对象new Cookie(name, value);
  • 设置最大时效 setMaxAge(int age);
  • 将Cookie 放入到HTTP响应报头(Set-Cookie:key=value)
String username = request.getParameter("username");
//创建一个Cookie
Cookie  cookie = new Cookie("usename", username);
//将cookie发送给浏览器
response.addCookie(cookie);

如果创建了一个Cookie,并将它发送到浏览器,默认情况下它是一个会话级别的cookie;存储在浏览器的内存中,用户退出浏览器之后被删除;

若希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设置为0则是命令浏览器删除该coolie;

发送cookie需要使用HttpServletResponse的addCookie方法,将cookie插入到一个Set-Cookie HTTP响应报头中

Cookie cookie = new Cookie("username", username);
//给一个cookie设置了一个预期时间,那么该cookie是一个持久化的cookie,该cookie
//将会保存在浏览器所在的硬盘上,浏览器关闭后不会消失,只有超过了这个期限,浏览器才不发送该cookie
cookie.setMaxAge(60*5);
response.addCookie(cookie);

读取Cookie

因为保存在浏览器上的cookie以请求头的形式发送,所以需要通过request获取客户端的cookie,如果没有cookie发送过来,requst.getCookie()返回null

修改Cookie

修改指定名字的cookie,就是再次向浏览器发送一个同名并且不同值的一个cookie,让其覆盖

删除Cookie

删除指定名字的cookie,就是再次向浏览器发送一个同名并且失效的cookie,让其覆盖

Cookie存储中文

因为Cookie数据传递是通过消息头的形式,而消息头中不能出现中文,所以在创建Cookie之前需要把数据编码成非中文。服务器接收浏览器发送的Cookie值时再解码出中文。

创建带有中文内容的Cookie:

//使用URLEncoder.encode方法把中文编码为application/x-www-form-urlencoded格式
Cookie cookie = new Cookie("username",URLEncoder.encode("中文","UTF-8"));
cookie.setMaxAge(60*5);
response.addCookie(cookie);

接收带有中文的Cookie:

Cookie[] cookies = request.getCookies();
if(cookies != null){
    for(Cookie cookie : cookies){
        if("username".equals(cookie.getName())){
            //使用URLDecoder把application/x-www-form-urlencoded格式反编码
            String value = URLDecoder.decode(cookie.getValue(), "UTF-8");
            break;
        }
    }
}

Session

什么是Session

  • Session机制采用的是在服务器端保持HTTP状态信息的方案;
  • 当程序需要为某个客户端的请求创建一个Session的时候,Servlet容器首先检查这个客户端的请求里是否已经包含了一个seesion id,如果已经包含一个seesion id则说明以前已经为次客户端创建过seesion,Servlet容器就按照session id把这个session检索出来使用(如果检索不到可能会创建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id。这个session id将会在本次响应中返回给客户端保存
  • 可以将Session看作是Map<String,Object>对象,session id靠cookie维护客户端和服务器之间的通信。

创建Session

在服务器上创建一个空间,并为该内存空间生成一个唯一的id,放在cookie中发送给客户端,通过request.getSession()方法得到该请求所在的会话。默认情况下,如果当前请求没有在一个存在的会话下,服务器会创建一个并返回

查询Session中的内容

通过request的getSessioin方法得到该请求所在的会话,通过session.getAttribute方法得到在session中对应key的值

HttpSession session = request.getSession();
User user = (User)session.getAttribute("user");

删除Session

HttpSession session = request.getSession();
//从session中删除user
httpSession.removeAttribute("user");
//或者让session失效
httpSession.invalidate();//让session失效

Session的超时管理

  • WEB服务器无法判断当前的客户端浏览器是否还会继续访问,也无法检测客户端浏览器是否关闭,所以,即使客户已经离开或关闭了浏览器,WEB服务器还要保留与之对应的HttpSession对象
  • 随着时间的推移而不断增加新的访问客户端,WEB服务器内存中将会因此积累起大量的不再被使用的HttpSession对象,并将最终导致服务器内存耗尽。
  • WEB服务器采用“超时限制”的办法来判断客户端是否还在继续访问,如果某个客户端在一定的时间之内没有发出后续请求,WEB服务器则认为客户端已经停止了活动,结束与该客户端的会话并将与之对应的HttpSession对象失效
  • 如果客户端浏览器超时之后再次发出访问请求,WEB服务器会认为这是一个新的会话的开始,将为之创建新的HttpSession对象和分配新的会话标识号。
  • 可以通过三种方式设置Session的超期时间:
    1.在web.xml中设置:
<!-- session-config包含一个子元素session-timeout,单位为分钟 -->
<session-config>
    <session-timeout>5</session-timeout>
</session-config>

2.使用session.setMaxInactiveInterval(秒)设置
3.优先级:

3.1:setMaxInactiveInterval优先级最高,如果setMaxInactiveInterval没有设置,则默认是session-config中设置的时间
3.2:setMaxInactiveInterval设置的是当前会话失效时间,不是整个web服务的。
3.3:setMaxInactiveInterval的参数是秒,session-config的是分钟
3.4:如果当前项目的web.xml中没有设置的话就使用tomcat/conf/web.xml中默认的配置

禁用Cookie的时候使用Session

由于cookie可以被人为地禁止,必须有其他机制以便在cookie被禁止时仍能够在服务器和客户端之间传递session id。经常被使用的一种技术叫URL重写,就是把seesion id直接附加在URL路径的后面