HTTP是无状态协议,为安全有效验证登录,记录用户登录状态,目前采用的验证机制主要有Session、Cookie和Token,三种机制互有利弊,文章简要分析三种机制的基本原理和特点,对比区别与联系。
1.Cookie
-
基本描述
由客户端浏览器保存在本地的一些数据,用来保存由服务器指定的用户信息。用户在访问服务器后,由服务器在响应包中通过HTTP头Set-Cookie
返回Cookie内容及限制条件,之后客户端再次访问时,携带相应的Cookie完成认证。 -
存储内容
以NAME=VALUE
键值对形式存储,包括用户数据、过期时间、路径、域名等信息,也可以包括SessionID和Token。 -
存储位置
由客户端浏览器保存在本地 -
有效时间
会话Cookie:如果不设置过期时间,则Cookie在会话结束后 (关闭浏览器) 销毁;
持久化Cookie:直到Set-Cookie
头设置的过期时间Cookie才销毁,可以设置很长时间 (几十年、几百年)。 -
认证方式
在HTTP请求的Cookie
头中携带相应信息 -
优点
① 用户信息保存在客户端本地,不占用服务器存储资源;
② 父域可以与子域共享Cookie,比如访问a.xx.com站点,请求中会携带xx.com域的Cookie;
③ 可根据访问URL路径使用不同的Cookie,比如设置path=/device
,则路径中包括/device
的请求才会携带该Cookie。 -
缺点
① 以文本的形式保存在本地,安全性较差;
② 数目限制(一般是50个),大小受限(一般是4096字节);
③ 并发访问量大时,服务端占用带宽多;
④ 需要客户端浏览器支持,移动端APP不适用;
⑤ 基于Cookie的认证方式容易遭受CSRF攻击。
2.Session
-
基本描述
在服务端保存的一种数据结构,用来保存用户信息。用户在访问服务器时,服务器为用户生成唯一的用户标识 (SessionID)并返回客户端,同时在服务端保存一份SessionID对应的用户数据,之后用户再次访问时,服务器通过请求中携带的SessionID匹配记录中对应的用户信息,完成认证。 -
存储内容
SessionID相对应的数据结构存储着用户信息,包括账户密码等隐私数据。 -
存储位置
服务器存储着完整的数据结构信息,可以存储在内存(sessionStorage)、数据库(localStorage)等位置;
客户端只保存SessionID,通常在Cookie中保存,也可以在内存(sessionStorage)、数据库(localStorage)中存储。 -
有效时间
一般在会话结束后 (退出登录或关闭浏览器) Session即失效,即便设置失效时间,为缓解服务器存储开销,一般也会比较短暂,一般为30分钟。 -
认证方式
① 基于Cookie信息,在HTTP请求的Cookie
头中携带;
② 基于URL重写,不同的后台语言携带Session的方式不同,比如:
jsp --> http://www.a.com/login.jsp;JSESSIONID=1?ie=utf-8&f=8
php --> http://www.a.com/login.jsp?PHPSESSID=1&ie=utf-8&f=8 -
优点
存储在服务器上,对用户是透明的,可以较好保证数据安全。 -
缺点
① 并发访问量大时,对服务器存储资源造成较大压力;
② 对于分布式服务器集群,存储信息难以共享;
③ 一般基于Cookie实现,存在CSRF风险;
④ 不可跨域,Session仅在所属域有效。
3.Token
-
基本描述
由服务端生成的一串字符串,作为用户请求服务时的令牌。在用户登录后,服务器对用户标识、生效时间、时间戳等信息使用HASH算法及密钥进行签名,并将这个签名和信息一起作为Token返回给客户端,之后用户每次访问服务器时携带Token进行验证,服务器获得请求后会再次用相同算法计算Token,通过对比进行验证。 -
存储内容
包括用户标识、生效时间、时间戳等信息以及对这些信息的签名 -
存储位置
客户端,通常存储在Cookie中,也可以存储在内存 (sessionStorage)、数据库 (localStorage) 等位置。 -
有效时间
根据应用场景灵活设置,一般为7天,若存储在sessionStorage中,则会话结束 (关闭浏览器) 时Token即失效。 -
认证方式
① 基于Cookie信息,在HTTP请求的Cookie
头中携带;
② 在HTTP请求头中携带,如:X-Token
、Authorization
;
④ 在HTTP请求的body中携带;
③ 通过URL拼接参数携带。 -
优点
① 服务端无需存储用户信息,相当于用CPU开销换取了存储开销;
② 无状态,扩展性强,可以跨域访问;
③ 不依赖浏览器,支持移动端APP;
④ 因为只有前端页面才能获取到当前会话保存的Token (比如js通过接口获取),而CSRF无法控制用户前端,恶意链接发送的请求中无法获取Token,因此能够有效防止CSRF。 -
缺点
① 并发访问量大时,占用服务器CPU资源;
② 无法在服务端注销,难以解决劫持问题。