背景
cookie与session都是为了保持访问客户与后端服务器的交互状态,有各自的优点也有各自的缺点。
cookie与session的关系非常紧密,对于不了解概念的同学经常会弄混淆,下面我从各个方面来介绍(用自己的理解)cookie和session。
Cookie
1.概念
cookie:客户端向服务端发起请求,服务端会传递一些key/value值给客户端,这样下次客户端访问服务器时,服务器能识别到客户的身份等信息,这对于互联网的体验,后端的区别处理都有重大的意义。这些key/value值会保存在客户端,称为"cookie"。
使用上来讲,它只是HTTP协议头中的一个字段。
2.属性值
当前cookie有两个版本:Version0和Version1
主要属性:
Expires:过期时间,在设置的某个时间点后该Cookie会失效
Domain:生成该Cookie的域名
Path:该Cookie是在当前哪个路径下生成的
Secure:如果设置该属性,那么只会在SSH连接时才会回传该Cookie
3.使用cookie的限制
Cookie是HTTP协议头中的一个字段,最终被存储在浏览器里,所以不同的浏览器对Cookie的存储都会有些限制,例如chrome,50个/每个域名,cookie总大小 大于8w个字节;firefox 50个/每个域名,4097个字节
Session
1. 概念
代表客户端与服务器的一次会话过程。客户端第一次访问服务器时会生成一个sessionID(服务器端生成的),每个客户端是唯一的,这样每次客户端和服务器交互,不需要每次都回传所有的Cookie值,只需要传回一个ID即可,这个ID通常是NAME为JSESIONID的一个Cookie。也即,session是基于Cookie实现的,是一个特殊的Cookie。
在Servlet中,session指的是HttpSession类的对象。
2. 存储
session存放在服务器端的内存中,不过session可以通过特殊的方式做持久化管理。
3. 生命周期
创建和使用:客户端第一次请求session对象时,如果没有,服务器会为客户端创建一个session,并生成一个sessionID,用来标识该session对象,当浏览器下次请求别的资源时,浏览器会将此sessionID放置在请求头中,服务器接收到请求后就得到该请求的sessionID,找到该ID的session返还给请求者使用。一个会话只有一个session对象,根据sessionID唯一确认。
删除:
1. session超时后删除
2. 调用HttpSession.invalidate()
3. 服务器关闭或服务停止
ps. session超时:超时是指连续一定时间服务器没有收到该Session所对应客户端的请求,并且这个时间超过了服务器设置的Session超时的最大时间。
cookie与session的对比
1. 安全性
cookie可以在浏览器中使用工具被查看、编辑、添加、修改,安全性令人堪忧;而session对象被保存在服务器端,通过cookie传递一个SessionID而已,更适合存用户隐私和重要的数据。
2. 一致性
Cookie能解决同一个用户的请求不在同一台服务器处理而导致的cookie不一致问题,简单而粗暴;而Session存储在服务器端,当一个应用由一个集群提供服务时,需要解决session同步的问题。
3. 存储
cookie存储在浏览器中,有大小限制,且当同一域名下有多个应用系统,cookie的使用和管理容易混乱、超出限制;而session的统一管理可以解决这些问题。
总而言之,session是为了弥补cookie的一些限制和缺点,作为解决方案而出现的。下面介绍session的分布式架构。
相关几个扩展
1. 分布式session架构
如下图,左上方有一个服务订阅服务器,在应用系统启动时,可以从这个订阅服务器订阅这个应用需要的、可写的session项和可写的cookie项,这些配置的session和cookie可以限制这个应用能够使用那些session和cookie,甚至可以控制session和cookie的可读或者可写,以有效控制session的安全性和cookie的数量。
通过统一的订阅服务器的推送配置,可以有效地集中管理资源,简化cookie的管理。
由于应用是一个集群,所以不可能将创建的Session都保存在每台应用服务器的内存中。所以若要共享,必须将它们存储在一个分布式缓存中,可随时读、写,MemCache或者淘宝开源的分布式缓存系统tair都可以选择。
如何实现session和cookie的读写?
1. 重新实现HttpSession操作接口,通过InnerHttpSession对象来操作session
2. 配置一个filter拦截用户请求,在请求进入应用前完成session和cookie的读写
2. 跨域名同步session
要实现跨域名session同步,需要另一个跳转应用(成为jump应用),这个应用可以被多个域名访问,主要功能是从一个域名下取得sessionID,然后将这个sessionID同步到另外一个域名下。
3. 解决cookie被盗
问题:登录成功后,cookie被盗,盗取人将你的cookie加入到他的浏览器,就可以通过你的cookie正常访问你的个人信息了
解决:在分布式session中,设置一个session签名,当用户登录成功后,根据用户的私密信息生成一个签名,以表示当前这个唯一合法的登录状态,将这个签名作为一个cookie在当前这个用户的浏览器进程中和服务器传递,用户每次访问服务器都检查这个签名和服务器从分布式缓存中取出的session重新生成的签名是否一致,如果不一致,则判断这个用户的登录状态不合法,服务器端将清除这个sessionID在分布式缓存中的session信息,让用户重新登录。 是否有性能问题?
4. 表单重复提交问题
网站中很多地方都有表单提交的问题,如网速慢、用户恶意发送重复请求,在这些场景下,需要设计一个拦截表单重复提交的机制。
防止表单提交,需要有一个字段标识用户的每一次提交,使得每一次提交都是唯一的。那么,可以在表单域里增加一个隐藏的表单项,这个表单项的值每次都是唯一的token。
当用户请求该页面时,生成唯一的token,并保存在用户的session中;等用户提交时,检查这个token和当前session中保存的token是否一致,如果一致,说明没有重复提交,否则,用户提交上来的token已经不是当前的这个请求的合法token。
小结
本文对cookie和session做了简要的介绍,它们都是为了保证客户端和服务端访问的连续性。为什么包保证连续性?一方面,用户体验上更良好,也方便后端的业务实现,另一方面,也可以简单后端实现,提高访问性能。cookie使用简单、但数量大小有限制,也存在安全问题,而session,基于cookie,作为补充,解决了安全、同步、跨域等问题,两者相辅相成,共同完成使命。