Web应用中4类登录会话管理机制
场景需求
保护资源是需要确认用户是谁及其权限才能操作的资源。应用软件通过认证机制来确认当前请求的用户是谁。但是用户显然不愿意每操作一个资源(URI)都提供一次账密,而是希望只提供一次账密,应用软件能够在一段时间内记住自己是谁,在这段时间内操作保护资源时,应用软件不要再向自己索要账密。为此,应用软件需要实现,在用户第一次提供账密并验证正确后,记住已经验证过他的账密了(设置标志),以及他是谁(颁发凭证,其中保存了用户id或用户名)。之后,用户再要求操作保护资源时,应用软件通过标志得知无需再向用户索要账密,通过凭证解析出用户是谁,从而同意其操作保护资源。当用户告知应用软件不要再记住自己是谁时,应用软件删除标志和凭证。此后,当用户要求操作保护资源时,应用软件会找不到标志和凭证,将要求用户提供账密。
背景概念
传递并验证用户账密的过程称为认证,设置标志和颁发凭证的过程称为登录,删除标志和凭证的过程称为登出,在登录到登出这段期间内的一系列请求\响应称为会话。登录标志、登录凭证、用户id、用户名称、会话到期时间等信息属于会话状态。
通常,应用软件会在认证通过的同时设置登录标志、颁发登录凭证。因此,上述4个概念之间往往存在以下联系:
- 认证通过 = 登录成功 = 开启会话
- 用户主动登出 = 结束会话 = 需重新认证
- 会话到期 = 用户被动登出 = 需重新认证
通常,在登录前、登出后、会话到期后这三个需要认证的时间段内,网络上传递的是账密;其余时间,网络上传递的是登录凭证。
会话管理:又称会话控制,是指应用软件通过采用某种方法来开启和结束会话,即实现登录和登出。
为此,必须考虑的问题是:
- 【Q1】客户端和服务器,谁负责保存会话状态?
- 【Q2】双方之间通过什么方式传递登录凭证?
这两个问题的解决方案可以统称为会话管理机制。实操中常见的会话管理机制分为4类:基于session、基于cookie、基于token、基于认证。
1 基于session的会话管理机制
1.1 本质特征
- 【Q1】会话状态保存在服务端,登录登出逻辑由服务器实现。
- 【Q2】通常使用浏览器的Cookie技术传递登录凭证,但并不意味着必须用Cookie,只要服务器和客户端约定好了,登录凭证可以放到HTTP请求的任何位置,例如放在头字段中、请求体中、URI的查询参数中。
1.2 会话过程
- 登录:服务器验证账密通过,随机生成一个唯一值(session id)作为登录凭证,将登录凭证、登录标志、用户id、用户名称、会话到期时间等会话状态封装成一个session对象,存储到服务端的内存或数据库中,然后把登录凭证(session id)通过Cookie值返回给客户端。客户端将Cookie值保存到本地
- 会话期间:客户端每次发请求时携带Cookie把登录凭证(session id)传递给服务器。服务器找出保存的session对象,根据登录标志、会话到期时间等判断是否需要重新认证。
- 登出:客户端携带Cookie向服务器的登出接口发请求,服务器清除session对象中的登录标志,或直接删除整个session对象,然后在响应中将Cookie值设为空。
1.3 优点
- 主流的Web服务器开发平台或框架原生支持,易于开发。
- 安全性好,登录凭证是随机字符串,不泄露用户信息,且难以通过伪造登录凭证冒充用户。
- 便于管理用户登录行为,例如统计总登录人数、登录次数、登陆设备,强制一个账号在同一时刻只能登录一台设备。
1.4 缺点
- 会话状态保存在服务端,增加服务器负担。
- 不易于扩展,采用集群部署时面临会话共享的问题,虽然可以通过redis中间服务器管理session等方式来解决,但又会增加架构的复杂性。
2 基于cookie的会话管理机制
2.1 本质特征
- 【Q1】会话状态保存在客户端,登录登出逻辑由服务器实现。
- 【Q2】利用浏览器的Cookie技术传递登录凭证。
2.2 会话过程
- 登录:服务器验证账密通过,把用户id、会话到期时间等会话状态拼接成字符串,经过签名(防篡改)、加密(防泄漏)生成一个不透明字符串,将这个不透明字符串(称为ticket)作为登录凭证,通过Cookie值返回给客户端。客户机将Cookie值保存到本地。
- 会话期间:客户端每次发请求时携带Cookie把登录凭证(ticket)传递给服务器。服务器解密登录凭证(ticket),校验签名。如果这两步失败,说明受到攻击。反之,说明用户已登录,则根据会话到期时间等判断是否需要重新认证。
- 登出:客户端携带Cookie向服务器的登出接口发请求,服务器通过在响应中将Cookie值设为空来清除保存在客户端的会话状态。
2.3 优点
- 主流的Web服务器开发平台或框架原生支持,客户端直接利用浏览器的Cookie技术,易于开发。
- 会话状态保存在客户端,减少服务器负担。
- 易于扩展,采用集群部署时只要签名秘钥、加密算法、生成和验证登录凭证的逻辑相同,就能轻易实现会话共享。
2.4 缺点
- 登录凭证是自包含的,有泄露和篡改风险,安全性的高低取决于加密算法、签名秘钥。
- 依赖于浏览器的Cookie技术,不适合有native app客户端的Web应用。
- 用户可能会禁用浏览器的Cookie。
- 不便于管理用户登录行为,例如统计总登录人数、登录次数、登陆设备,强制一个账号在同一时刻只能登录一台设备。
3 基于token的会话管理机制
3.1 本质特征
- 【Q1】会话状态保存在客户端,登录逻辑由服务器实现,登出逻辑由客户端实现。
- 【Q2】客户端主动在请求头中添加约定字段传递登录凭证。
3.2 会话过程
- 登录:服务器验证账密通过,把用户id、会话到期时间等会话状态拼接成字符串,经过签名(防篡改)、加密(防泄漏)生成一个不透明字符串,将这个不透明字符串(称为token)作为登录凭证,通过响应头的某个约定字段,或响应体的某个约定参数返回给客户端。客户端将token保存到本地。
- 会话期间:客户端每次发请求时必须主动在请求头中添加约定字段把登录凭证(token)传递给服务器。服务器解密登录凭证(token),校验签名。如果这两步失败,说明受到攻击。反之,说明用户已登录,则根据会话到期时间等判断是否需要重新认证。
- 登出:服务器无法控制客户端清除会话状态,当用户要登出时,客户端需自己清除会话状态,不用向服务器发请求。
3.3 优点
- 会话状态保存在客户端,减少服务器负担。
- 易于扩展,采用集群部署时只要签名秘钥、加密算法、生成和验证登录凭证的逻辑相同,就能轻易实现会话共享。
- 不依赖于浏览器的Cookie技术,适合有native app客户端的Web应用。
3.4 缺点
- 客户端与服务器需约定好传递用的头字段,客户端需自己实现对登录凭证的缓存、管理、主动传递,开发难度略高一点。
- 登录凭证是自包含的,有泄露和篡改风险,安全性的高低取决于加密算法、签名秘钥。
- 不便于管理用户登录行为,例如统计总登录人数、登录次数、登陆设备,强制一个账号在同一时刻只能登录一台设备。
4 基于认证的会话管理机制
4.1 本质特征
- 【Q1】会话状态保存在客户端,登录登出逻辑由客户端实现。
- 【Q2】客户端不传递登录凭证,而是对每个请求都传递账密编码值,服务器对每个请求都做一次认证。
当基于认证的会话管理机制与HTTP标准认证机制(Basic、Digest、Mutual等)结合使用时,非常适合REST架构风格的Web应用。
4.2 会话过程
以下会话过程涉及了HTTP标准认证机制的【质询-回答】框架,及其定义的概念——保护空间(realm):用于让服务器指示客户端在什么范围内自动发送已缓存的账密,它的作用类似于Cookie技术中的domain、path这两个参数(用于让服务器指示客户端在什么范围内自动发送已缓存的Cookie)。
- 登录:服务器验证账密通过,直接返回保护资源。客户端收到保护资源,就知道了认证已通过,于是在本地保存一系列键值对(path、host、realm、认证机制名称、用户名、密码、登录标志、会话到期时间等),并标记用户已处于登录状态(登录标志=True)。
- 会话期间:客户端对属于同一保护空间(host、realm、认证机制名称相同)的所有URI自动在请求头中增加
Authorization
字段传递账密编码值。服务器对每个请求都做一次认证。 - 登出:客户端让用户选择是否保留已缓存的账密:
(1)如果用户选择保留,则客户端标记用户已处于登出状态(登录标志=False)。
(2)如果用户选择不保留,则客户端删除账密和登录标志。
登出只需客户端操作本地数据,无需发送任何请求给服务器。 - 登出后再此访问该站点:
(1)在不保留账密的情况下,客户端检索path,发现其所属的保护空间没有缓存账密。客户端不带Authorization
字段发请求,服务器返回401质询,客户端重复登录步骤。
(2)在保留账密的情况下,客户端检索path,发现该保护空间下有已缓存的账密且未登录(登录标志=False)。客户端不带Authorization
字段发请求,服务器返回401质询。客户端弹出输入框并自动填充已缓存的账密,询问用户是否选择用此账密登录。用户确认后,客户端带Authorization
字段发请求,认证通过后(即服务器返回了保护资源),客户端标记用户已处于登录状态(登录标志=True)。 - 会话到期:用户登录后很长时间没访问该站点,也未曾登出,再次访问时,客户端检索到用户已在该保护空间登录,但已超出会话到期时间,则不带
Authorization
字段发请求,服务器返回401质询,客户端重复登录步骤。
4.3 优点
- 会话状态、登录登出逻辑都保存在客户端,服务器负担最少。
- 非常易于扩展,服务器只负责认证,采用集群部署时根本不会面临会话共享的问题。
- 不依赖于Cookie,适合有native app客户端的Web应用。
- 主流的Web服务器开发平台、框架、浏览器原生支持多种HTTP标准认证机制,易于开发。
4.4 缺点
- 频繁在网络上传输认证信息,安全性的高低取决于所采用的认证机制的安全等级(Basic < Digest < Mutual)。
- 不便于管理用户登录行为,例如统计总登录人数、登录次数、登陆设备,强制一个账号在同一时刻只能登录一台设备。
哪些会话管理机制不符合REST,哪些符合?
详解Web应用中的各种状态(会话状态、应用状态、有状态协议、无状态协议、REST无状态约束)
不符合REST
-
基于session的会话管理机制,存在以下三个问题,不符合REST:
(1)利用了在服务端保存的会话状态,违背了REST的无状态约束;
(2)将Cookie与特定的站点相关联,违背了REST的应用状态模型;
(3)Cookie值不透明,违背了REST对于可见性的要求。 -
基于cookie的会话管理机制,存在(2)、(3)两个问题,也不符合REST。
-
基于token的会话管理机制,存在类似(2)、(3)的两个问题(在对特定站点的未来请求中都发送该token、token值不透明),也不符合REST。
符合REST
- 基于认证的会话管理机制,其特点是客户端不传递登录凭证,而是对每个请求都传递账密编码值,服务器对每个请求都做一次认证。当它与HTTP标准认证机制(Basic、Digest、Mutual等)结合使用时,是符合REST的:
- 会话状态保存在客户端,登录登出逻辑由客户端实现,符合REST的无状态约束。
- 账密编码值与客户端中特定的应用状态相关联,即客户端只对需要认证的URI发送账密编码值,符合REST的应用状态模型。
- 客户端负责按照认证机制的规则生成账密编码值,符合REST对于可见性的要求。