1、会话的概念

会话(session),指的是web应用程序中客户端浏览器发出请求到服务器响应客户端请求的全过程。

2、什么是会话跟踪

对同一个用户对服务器的连续的请求和接收响应的监视。

3、为什么需要会话跟踪

浏览器与服务器之间的通信是通过HTTP协议进行通信的,而HTTP协议是“无状态”的协议(早期主要用于web端获取内容,浏览了就结束,没有考虑交互的场景,所以服务器不会保留与用户交易的任何状态),客户端与服务器之间的联系是离散的、非连续的。

多次请求,无法根据前后的请求来判断是否是同一个用户,面对越来越多的交互场景,会话跟踪技术应运而生。

4、会话跟踪技术

从原理上分析,一次请求和响应主要参与的有服务器、客户端,以及通信的HTTP协议,多以分别从这三方面考虑,会话跟踪技术主要有以下四种:

(1)Cookie

(2)url重写

(3)隐藏表单域

(4)Session

4.1 Cookie

是最常用的跟踪用户会话的方式,在客户端保持会话跟踪的解决方案,Cookie是以键值对形式存在片段信息,保存在客户端浏览器。

当用户第一次请求服务时,Cookie信息会随着服务器端的响应发送给客户端浏览器,然后客户都浏览器会把Cookie保存起来,当下一次客户端在发起请求时携带此信息作为用户的唯一标识发送给服务器。

Http的Cookie规范

  • 1个Cookie的大小不超过4KB
  • 1个服务器最多向一个浏览器保存20个Cookie
  • 1个浏览器最多可以保存300个Cookie

Cookie的用途

  • 服务器使用Cookie来跟踪客户端状态
  • 保存部分业务信息
  • 显示上次登录信息

Cookie与HTTP头

Cookie是通过HTTP请求头和响应头在客户端和服务器之间传递的

  • Set-Cookie

    响应头,服务器发送给客户端,通过 set-cookie方法设置

  • Cookie

    请求头,客户端发送给服务器端,key-value形式

Cookie常用方法

方法 描述
getName() 返回cookie的名称。
getPath() 返回浏览器返回此cookie的服务器上的路径。
getValue() 返回cookie的值
getMaxAge() 返回cookie的最大年龄。以秒为单位指定。默认情况下,-1指cookie将持续存在直到浏览器关闭。
getDomain() 返回为此cookie设置的域名。
setDomain(java.lang.String pattern) 指定应在其中显示此cookie的域
setMaxAge(int expiry) 以秒为单位设置cookie的最大年龄
setPath(java.lang.String uri) 指定客户端返回cookie的cookie路径。
setValue(java.lang.String newValue) 创建cookie后,为cookie分配新值。

构造Cookie对象示例

Cookie c1=new Cookie("aaa","123456");
c1.setMaxAge(60);//设置有效时间
response.addCookie(c1);//将cookie对象响应给客户端浏览器,存储在客户端

优点

  • 方便,简单

缺点

  • 只支持Ascii字符形式
  • 不能跨浏览器使用

4.2 URL重写

客户程序在每个URL的尾部添加一些额外数据(以键值对的形式传递),这些数据标识当前的会话,服务器将这个标识符与它存储的用户相关数据关联起来。通常是添加 sessionID作为会话信息的标识。

http://172.23.22.58:8081/jjyhf;jsessionid=123456789

对于重写的URL,服务器端程序要做许多简单但是冗长乏味的处理任务。

  • 通过Servlet容器解释URL,将对应的会话信息SessionId从URL中读取出来
  • 通过SessionId将请求和特定的Session关联,确认为同一会话
  • 完成服务处理,发送给服务端的URL也进行重写编码

优点

  • 浏览器不支持 cookie 或在用户禁用 cookie 的情况下,这种方案也能够工作

缺点

  • 必须对所有指向本 Web 站点的 URL 进行编码;
  • 参数在URL中,有长度限制;
  • 如果用户离开了会话并通过书签或链接再次回来,由于存储下来的链接含有错误的标识信息,会话的信息会丢失;
  • 用户 ID 及登录密码等重要信息可能以参数的形式暴露在URL上,造成安全隐患

4.3 隐藏表单域

隐藏表单域是利用 HTML 中的隐藏域,在网页表单内隐藏某些客户端的信息。在提交表单时,要将指定的名称和值自动包括在请求实体中,这些信息会随客户端的请求信息一起传送给服务器,服务器通过获取的这些信息来进行会话跟踪。
这些识别信息是隐藏的,所以不会在客户端的浏览器页面上显示,但是,如果查看 HTML 的源文件,是可以看到这些隐藏字段的,这样很可能会导致用户资料的泄露。显然,这是使用隐藏域方式的一个缺陷

<form name="testform" action="/xxx">
	//隐藏域
	<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
	<input type="text">
</form>

很显然,仅当每个页面都是由表单提交而动态生成时,才能使用这种方法。比如,单击常规的超文本链接并不产生表单提交,因此隐藏的表单域不能支持通常的会话跟踪,只能用于一系列特定的操作中。

优点

  • 存储内容不限;
  • 浏览器不支持 cookie 或在用户禁用 cookie 的情况下,这种方案也能够工作;

缺点

  • 依赖表单提交;
  • 如果大量隐藏表单且value数据量较大,会影响页面渲染

4.4 Session

Session是指使用后HttpSession对象实现会话跟踪的技术,是一种在服务器端保持会话跟踪的解决方案。

HttpSession是由JavaWeb提供的对象,是javax.servlet.http.HttpSession接口的实例,用来会话跟踪的类,也称为会话对象。是服务器端对象,保存在服务器端中。
HttpSession对象会在用户第一次访问服务器时由容器创建(注意只有访问JSP,Servlet等程序时才会创建,只访问HTML,IMAGE等静态资源并不会创建),当用户调用其失效方法(invalidate()方法)或超过其最大不活动时间会失效。在此期间,用户与服务器之间的多次请求都属于同一个会话。

比如,用户认证流程,客户端向服务器端发送请求,接收到请求后,Servlet容器为HttpSession对象分配一个唯一的SessionID,将其作为Cookie(或者作为URL的一部分,利用URL重写机制)发送给浏览器,浏览器在内存中保存这个Cookie。当客户再次发送HTTP请求时,浏览器将Cookie随请求一起发送,Servlet容器从请求对象中获取SessionID,然后根据SessionID找到对应的HttpSession对象,从而得到客户的状态信息。

会话范围

会话范围是某个用户从首次访问服务器开始,到该用户关闭浏览器结束

获取HttpSession对象

  • Servlet中获取HttpSession对象
    HttpSession session = request.getSesssion():如果当前会话已经有了session对象那么直接返回,如果当前会话还不存在会话,那么创建session并返回;

  • jsp中获取HttpSession对象
    session是jsp内置对象之下,不用创建就可以直接使用

session域相关方法

方法 描述
setAttribute(String name, Object value) 用来存储一个对象,也可以称之为存储一个域属性
getAttribute(String name) 用来获取session中的数据
removeAttribute(String name) 用来移除HttpSession中的域属性
getAttributeNames() 获取所有域属性的名称

构造Session对象示例

/** * 附加功能:把用户名保存到cookie中,发送给客户端浏览器 */
Cookie cookie = new Cookie("uname",username);//创建Cookie
cookie.setMaxAge(60*60*24);//设置Cookie的时长为一天
response.addCookie(cookie);//保存cookie

/** * 保存用户信息到session中 */
HttpSession session = request.getSession();//获取seession
session.setAttribute("usuername",username);//向session域中保存用户名

四种会话跟踪技术对比分析

Cookie Session URL重写 隐藏表单域
存放位置 客户端 服务端 url 页面
参数 请求头中,有大小限制 位置不定(取决于基础技术),无大小限制 url,1024长度限制 请求实体,无大小限制
请求方式 不限 不限 不限 不支持GET
Cookie禁用(客户端浏览器) 受影响 可以工作 可以工作 可以工作
持久性 取决于浏览器保存事件/过期时间 自定义失效时间 浏览器关闭 浏览器关闭