一、引言
动态网页兴起后,会话管理变成开发者需要考虑的一个问题,由于HTTP请求是无状态的,为了区分每个用户,此时引入了会话标识(session id)的概念,但是存储机制也会产生不同的问题,下面就详细分析一下三种机制的优缺点以及使用方式。
二、session
定义:会话,打开web应用时产生,浏览器第一次访问服务器会在服务器端生成一个session,有一个sessionid和它对应。
创建:session在访问tomcat服务器时调用HttpServletRequest.getSession(true)创建。(此时对应的sessionid也同时产生)
存储:session的状态信息等储存在服务器的内存中,但是sessionid是保存客户端的cookie中,客户端不保存session,session销毁只能通过invalidate或超时失效,关掉浏览器并不会关闭session。
原理:
- 1、浏览器向服务器发送登录请求(post),携带账号和密码
- 2、登录成功,服务器记录登录的状态,req.session.user = user; 服务器记录这些信息
- 3、服务器返回的响应头中携带服务器生成的 sessionid(cookie中),身份标示
- 4、浏览器再次访问服务器的时候会通过cookie携带sessionid
- 5、服务器获取浏览器发送的sessionid后,在服务器查找sessionid,如果找不到,未登录
- 6、如果找到 sessionid,根据 sessionid 查找对应的对象,登录成功
删除:(1)超时;
(2)程序调用HttpSession.invalidate();
(3)程序关闭;
存在的问题:(1)负载均衡后,每台机器间的session都需要相互复制,很烦杂
(2)单独把session拿出来存,又会面临这台存session的服务器一宕机,全部的用户都得重新登陆,凉凉...
常见QA:
Q:浏览器关闭时,session会同时关闭么?
A:session并不会因为浏览器的关闭而删除!关闭浏览器和session失效没有任何关系, session本身有一个存活时间,在tomcat中默认的是30分钟,打个比方即使浏览器一直开着,如果在30分钟内没有发出任何请求, 那原来存在服务器上的session域内的东西就全没有了, 再次访问的时候,服务器会新建一个session。它的改变是通过session.getMaxInactiveInterval()改变的,当关闭浏览器,再打开浏览器访问的时候,服务器会新建一个session,可以通过session的ID来判断是不是新的session,session的失效除了上述的超时,还有调用invalidate() 或者服务器重启或者中断,所以如果当设置session的MaxInactiveInterval为-1(永不超时)时,并且关闭了浏览器,那么你的session会一直存在,除非重启服务器。
三、cookie
定义:由服务器生成的一小段文本信息,发送给浏览器,浏览器把cookie以kv形式保存到本地某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。
存储:保存在本地客户端。
原理:
- 1、客户端发送一个请求(http请求+用户认证信息)到服务器
- 2、认证成功,服务器发送一个HttpResponse响应到客户端,其中包含Set-Cookie的头部
- 3、客户端提取并保存cookie于内存或磁盘
- 4、再次请求时,HttpRequest请求中会包含一个已认证的Cookie的头部
- 5、服务器解析cookie,获取cookie中客户端的相关信息
- 6、服务器返回响应数据
删除:(1)超时;(设置了过期时间,cookie过期后会存储在硬盘里面)
(2)手动删除;
存在的问题:(1)cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗。
(2)cookie有安全隐患,通过拦截或本地文件找得到你的cookie后可以进行攻击。
(3)cookie有大小限制以及浏览器在存cookie的个数也有限制。
四、token
定义:令牌,是一种用户身份的验证方式。
目的:为了减少服务器压力,避免客户端频繁向服务端请求数据,从而频繁查询数据库。
创建:第一次登录后,服务器生成一个Token便将此Token返回给客户端
存储:token一般储存在客户端的cookie中,服务端生成后不保存token(可以存在缓存中),服务端处理每次请求,只做token的校验工作而已。
常见组成方式:uid(用户唯一的身份标识) + time(当前时间的时间戳) + sign(签名,由token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token请求服务器)。
原理:
- 1、用户通过用户名和密码发送请求。
- 2、程序验证。
- 3、程序返回一个签名的token 给客户端。
- 4、客户端储存token,并且每次用于每次发送请求。
- 5、再次请求时,服务端验证token并返回数据。
PS:第一次登陆时,客户端传账号和密码到服务器,服务器先去查询数据库,查询到用户信息后服务器再根据自己的规则生成token并缓存(如redis等技术),再把token回传给客户端(客户端可以把token存到cookie中)。
第二次登陆时,直接传token给服务器验证缓存中是否存在该token;也可以传账号密码给服务器,让服务器再次生成一次token,用这次生成的token去缓存中校验是否存在。
参考资料: