会话管理分为两类
- 基于session的身份验证(即有状态会话管理)
- 基于令牌的身份验证(即无状态会话管理)
基于session的身份验证(即有状态会话管理)
在基于会话的身份验证中,由服务器负责验证工作。广义上讲,客户端使用其凭据进行身份验证,并接收session_id (通常存储在cookie中,也可以存储在sessionstorage/localstorage或者指定的变量中),格式通常是一串毫无意义的字符,也可以是由服务端语言生成的UUID,甚至也可以是JWT,并将其附加到每个后续的发出请求中,重点是服务端要存储session_id,通常session_id的存储位置是内存,涉及到持久化或者其他需要时也会存储到硬盘中,session_id的生命周期和清除机制与由浏览器(用户代理)和服务端的HTTP连接有关,在HTTP连接丢失或失活后,根据服务端动态语言(php,java)的的配置session存活时间,达到存活时间后就自动清除。在持续的HTTP访问的情况下每一次访问session存活时间就会重新开始计时,即session生命周期得到延长。因此当浏览器关闭(HTTP连接结束)或用户退出后,服务端会清除session,这样session_id就无法被重用,特别的,即使是同一台计算机,不同浏览器与服务端之间http连接创建出的session其session_id也是不同的。
优点:
- 它是不透明的,不携带有意义的数据,因此第三者无法从中获得任何意义
- 它也可以用标志来保护
缺点:
- 服务器将用户会话存储在数据库,缓存或内存中
- 必须针对CRSF进行保护
基于令牌的身份验证(即无状态会话管理)
在基于令牌的身份验证,JWT已成为事实上的标准,不会在服务器端保留会话(无状态)。凭证附加到每个请求中(可以存储在cookie中,也可以存储在sessionstorage/localstorage或者指定的变量中)。 只要JWT处于有效期内,服务端通过程序解读后如果认为JWT合法则认为访问和用户合法(虽然随JWT传过来的有user agent端的ip,user agent所处的其他环境,通过加强检查环境来保证JWT的合法,但终究没有从根源处理JWT被盗用的情况)。
优点
- 服务器不需要存储会话
- 涉及多端认证支持时程序开发方便
缺点
- 服务器仍然需要存储列入黑名单的令牌,这会破坏无状态的目的
- 扩展时,需要在服务器之间提供秘钥
- 存储在令牌中的数据可能会过时,因为它已被缓存
- 最重要的是,它容易受到XSS攻击。意味着任何恶意代码,脚本或攻击都可以在受到威胁时获得访问权限或窃取用户信息,权限等
问题或误区
1. 哪个实施更安全?
会话认证。 原因如下:
- 无论哪种方式,您仍然需要维护服务器状态
- 您的数据存储在服务器端始终比客户端更安全
- 与XSS相比,缓解CSRF攻击非常容易或更容易
- 会话易于管理
- 数据永不过时
2. 使用cookie发送令牌一定是有状态身份验证
错误。JWT/access_token和或者会话标识本质上都是一串随机字符串,都可以用于session会话标识,因此无法从数据格式、数据存储位置、数据发送方式上确定当前的会话管理是否一定是或者一定不是有状态会话验证。
3. 使用header <authorization:bearer [jwt]>一定是无状态会话验证
错误。原因同上。
4. 使用JWT格式向服务端传送数据来实现会话管理一定是无状态会话管理。
基本正确。目前除JWT格式以外,尚没有其他的规范能够安全的表示用户身份。当然JWT本质是一种非对称加密,因此从广义上来讲,使用非对称方式加密用户身份后的令牌都可以用于无状态会话管理
参考:
github-servicecomb-fence微服务认证鉴权支持
stackoverflow-Dalton Cézane-Sessions vs. Token based authentication
博客园-SolidMango-Session, Token and SSO 有什么区别
简书-大宽宽-实现一个靠谱的Web认证
知乎-liubao68-无状态会话管理和有状态会话管理对比分析