会话跟踪技术:Cookie、Session和Token
会话跟踪技术
- 背景:
- 1. Cookie (客户端的会话跟踪技术)
- 1.1 原理
- 1.2 基本使用
- 1.2.1 服务器发送Cookie
- 1.2.2 服务器获取Cookie
- 1.3 使用细节
- 1.3.1 存活时间
- 1.3.2 存储中文
- 2. Session(服务端的会话跟踪技术)
- 2.1 原理
- 2.2 基本使用
- 2.2.1 获取Session对象
- 2.2.1 Session对象的功能
- 2.3 使用细节
- 2.3.1 Session钝化、活化
- 2.3.2 Session销毁
- Cookie与Session的区别:
- 3. Token
背景:
HTTP是无状态的协议,即服务器对客户端没有记忆能力,它的每个请求都是完全独立的,发送请求不涉及到状态变更。
无状态的后果: 意味着后续发出的请求需要先处理前面请求的响应,则必须重传前面的请求,这导致需要额外传递一些前面的重复请求,才能获取后续响应,会大大浪费资源;
-------------所以需要 会话跟踪技术 来解决无状态的问题 !实现一次会话的多次请求内数据共享!
1. Cookie (客户端的会话跟踪技术)
Cookie的实现是基于HTTP协议的;
Cookie是客户端保存用户信息的一种机制 ,本质是存储在浏览器的一小段文本数据,不超过4kb;
过程:
【第一次发送HTTP请求时】,服务器产生Cookie并返回给浏览器存储,
【以后浏览器每次发送HTTP请求时】,HTTP的请求报文的请求头中都会带着Cookie(请求头的格式为字段名和value值)
缺点: 安全性
- Cookie是放在【HTTP请求报文】的头部行中,是以明文形式在网络中传输,若没有加密,一旦被截获,可以直接获取隐私信息;
- 即使是Cookie被MD5加密,一旦Cookie被截获,把别人的Cookie向服务器提交,并且能够通过验证,就可以冒充受害人的身份登陆网站--------Cookie欺骗。
1.1 原理
- 在servletA创建了Cookie对象并封装在respond对象中,
- Tomcat解析respond对象,会将Coockie键值对放到HTTP响应报文的 响应头
set-cookie
:username=zs - 浏览器拿到并解析响应报文,拿到数据username=zs并存储;
- 当下一次浏览器要访问servletB,会在HTTP请求报文的 请求头 中带上:
cookie
:username=zs - Tomcat解析浏览器发送的HTTP请求报文,将数据存入request对象,通过request对象来获取Cookie数组;
1.2 基本使用
作为服务端,需要关注的:
①发送Cookie,
②接收到Cookie后获取其中的信息
1.2.1 服务器发送Cookie
-
在Servlet中,创建Cookie对象,设置数据;
-
将Cookie对象添加到Response对象,而后由Tomcat读取respond中数据并拼接成HTTP响应报文格式发给客户端;
例:发送Cookie
启动Tomcat,访问aServlet就会执行cookie相关代码;
查看响应报文(响应头):
此时打开浏览器设置,能找到刚才发送的Cookie:
1.2.2 服务器获取Cookie
注:浏览器访问服务器时会在HTTP请求报文的请求头中带着所有Cookie,每对用分号隔开;
- 使用request对象来获取Cookie数组
- 遍历Cookie数组,获取每一个Cookie
- 使用Cookie对象方法获取数据;
例:获取Cookie数组,只取出name=”username“的那个Cookie,打印出name和value:
此时访问bServlet,浏览器携带了Cookie,由servlet获取,在控制台打印:
1.3 使用细节
1.3.1 存活时间
【默认情况下】,Cookie存储在浏览器内存中,当浏览器关闭,内存释放,Cookie会被销毁;
Cookie持久化: setMaxAge(int seconds)
设置Cookie存活时间;
- 正数:将Cookie写入浏览器所在磁盘,持久化存储!到时间自动删除
- 负数,默认值,Cookie存在浏览器内存中,浏览器关闭,则Cookie被销毁
- 零:删除对应Cookie
1.3.2 存储中文
默认情况下不能存储中文!
解决:
- 将value用URL编码;
- 中文被编码为:
- 再对value进行解码:
成功解码:
2. Session(服务端的会话跟踪技术)
Session机制一般借助Cookie来实现;
session对象存储在服务器中,用于记录用户的状态,
sessionID是无规律的字符串,存储在浏览器端的【Cookie中】;
当浏览器【发送HTTP请求时】会带着sessionID,服务器根据SessionID就能找出用户信息;
session会配置一个过期时间(默认30min),过期后需要重新登录;
当客户端第一次访问服务器时,【服务器创建session出来后】,会把sessionID以cookie的形式回写给客户机,这样,只要客户机的浏览器不关,再去访问服务器时,都会带着session的id号,服务器发现客户机浏览器带sessionID过来了,就会使用中与之对应的session为之服务。
运行机制:
1.主机的浏览器进程与服务器进程建立浏览器连接
2.当用户浏览器进程【第一次向服务器进程发送HTTP请求报文时】,服务器进程就会为其产生一个唯一的sessionID,并以此为索引在服务器的后端数据库创建session对象,用来记录该用户访问该网站的各种信息
3.接着服务器给浏览器进程发回HTTP响应报文,在响应报文中,包含一个首部字段为Set-Cookie的首部行,该字段由服务器写入了sessionID,以及会话结束时间
4.当浏览器进程收到该响应报文后,就在一个特定的Cookie文件中添加一行,记录该服务器的域名和Cookie;
5.【当用户再次使用浏览器访问这个网站时】,每发送一个HTTP请求报文,浏览器都会从Cookie文件中取出该网站的sessionID,并放到HTTP请求报文的Cookie 头部行 中,服务器根据sessionID就可以识别该用户,返回相关信息;
2.1 原理
Session是基于Cookie实现的;
为什么在一次会话的多次请求之间获取的都是同一个Session对象 ?
浏览器访问服务端,servlet会自动生成Session对象的ID并放入Cookie,发给浏览器(HTTP响应报文的响应头);
浏览器收到后将SessionID存入内存/磁盘;
下次浏览器携带着Cookie:SessionID=10 访问Servlet,Servlet收到SessionID后寻找这个SessionID的对象,如果有就直接使用,没有则创建新的Session对象;
而当另一个浏览器的请求3访问Servlet时没有携带sessionID或者不一样,servlet就无法获取刚才sessionID=10的SessionID对象,这就保证了同一个会话的session是同一个;
2.2 基本使用
2.2.1 获取Session对象
2.2.1 Session对象的功能
注:setAttribute的值可以存任意类型!
例:
ServletDemo1:通过request对象获取Session对象并存数据
ServletDemo2:读取Session并获取数据
输出zs;
即session对象被两次请求所访问,即在一次会话的两次请求之间共享数据!
2.3 使用细节
2.3.1 Session钝化、活化
钝化(序列号):【服务器正常关闭后】,Tomcat会自动将Session数据写入硬盘的文件中;
活化(反序列化):再次启动服务器后,从文件加载数据;
Session是对象,钝化即序列号,活化即反序列化;
2.3.2 Session销毁
-
默认情况下,误操作,Session会在
30
分钟内销毁(提示:登陆时间太长没有操作,已经自动退出请重新登陆)
也可以在xml文件中设置时间:
-
调用Session对象的
invalidate()
方法,如前端用户选择“登出”时,就需要销毁Session !
注意:
浏览器中途关闭,再次访问时,不是同一个Session对象,因为已经不是同一次会话了!
Cookie与Session的区别:
Cookie和Session都是完成一次会话多次请求间的数据共享;
- 储存:cookie储存在浏览器内存/磁盘,
session对象储存在服务器中,而sessionID存于Cookie中, - 安全性:session比cookie更加安全
①Cookie存在客户端,每次都在网络中传输,容易被盗取、截获;
②seesionID是随机字符串而不是明文,避免了直接存用户名密码,提高安全性;
③有会话时间限制,且可以选择使用签名,而cookie容易造成cookie欺骗 - 数据类型不同:cookie只支持字符串数据,session对象可以储存任意类型数据(Object)!
- 有效期不同:cookie存活时间可设置较长时间,而session存活时间相对较短(默认30min);
- 存储大小不同:单个cookie的数据不能超过4KB,session储存的数据内容可以更大;
3. Token
引入:Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生
token的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个令牌,当用户第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码,减轻服务器的压力。
运行机制:
1.客户端使用用户名跟密码请求登录;
2.服务端收到请求,去验证用户名与密码;
3.验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端;
4.客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里;
5.客户端每次向服务端请求资源的时候需要带着服务端签发的 Token;
6.服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据。
服务器并不保存token,而是通过数据签名的方法,对数据用算法(如SHA-256)与私钥进行签名后作为Token,当Token发送给服务器时,服务会通过相同的算法与密钥进行签名,如果和Token中的签名相同,服务器就知道用户已经登录过了,并且可以直接得到用户的userID。(服务器用cpu的计算时间来换取了储存空间)
token和session的区别?
token和session其实都是为了身份验证
服务端session存用户数据,客户端访问服务端的时候,根据sessionid找用户数据;而使用token时服务端只有一段加密代码;
同样,session和token都是有过期时间一说,都需要去管理过期时间;
其实token与session的问题是一种时间与空间的博弈问题,session是空间换时间,而token是时间换空间。两者的选择要看具体情况而定。
虽然确实都是“客户端记录,每次访问携带”,但使用token则后端不需要记录什么东西,每次解密验证即可;
而 sessionid ,一般都是一段随机字符串,需要到后端去检索 id 的有效性