在讲Token之前,先简单说说什么是 Session 和 Cookie。
首先要知道 HTTP 请求是无状态的;
无状态的意思就是:每一次请求都是独立的;每一次请求不会受到前面请求的影响,也不会影响后面的请求;
比如我们登录一个系统的时候,验证用户名密码之后,打开系统各个页面的时候就不需要再进行登录操作了,直到我们主动退出登录或超时退出登录;为了让服务器有“记忆功能”,我们可以用到 Session、Cookie。
01.Cookie
是在客户端(浏览器)保存用户信息的一种机制;Cookie 由服务器生成,发送给浏览器,然后浏览器把 Cookie 以键值对的形式保存在客户端的某个目录下面;每种浏览器存储大小会有一些差异,一般不超过 4KB;
当下一次请求的时候,会把 Cookie 发送给服务端,服务端对 Cookie 中的信息解析并验证身份。
比如你入职一个公司,会给你办一张工卡,上面有你的姓名、工号、部门等信息,你进入职场的时候,拿着工卡就可以进出。
但是 Cookie 是不可以跨域名使用的;就好像我拿着我们公司的工卡,去你们公司,保安肯定是不会放我进去的。
02.Session
保存在服务端,可以用于记录客户状态;
比如我们经常会用 Session 保存客户的基本信息、权限信息等;用户第一次登录之后,服务器就会创建一个 Session ,并将 SessionID 返回给浏览器,浏览器通常将其写入到 Cookie 中,这种 Cookie 也叫做 SessionCookie ,浏览器再次访问时,只需要拿着 SessionID 从服务端查找 Session 就可以了。
另外,这个 SessionID 不一定非要保存到 Cookie 中,只是对于浏览器客户端,大家的默认做法是放在 Cookie 中。
03.Cookie 和 Session
关于 Cookie 和 Session 的区别,很多同学会回答:“Cookie 保存在客户端,Session 保存在服务器端”,其实这样的想法并不全面:
Cookie 是一个实际存在的的东西,一个很具体的东西,就是一段数据,而 Session 是一个抽象概念,或者叫做模式方法,它有很多实现方案;
比如 Tomcat 的实现方法:把状态保存在服务端,然后生成一个 JSESSIONID 放在 Cookie 中;请求过来之后,拿着 JSESSIONID 在服务器端查询并验证状态。
04.Token
当然,随着用户量的增加,保存在服务端的 Session 也不断增加,这给服务端带来了很大的压力,并且如果程序是集群或分布式方式部署,同一个用户第一次请求,访问到了 A 服务器,创建了 Session,但是第二次请求却发到了 B 服务器上,但是 B 服务器上并没有之前创建的 Session;这就是分布式架构中的 Session 共享问题。
针对这个问题,我们可以进行服务器之间的 Session 同步,或者干脆把 Session 保存到第三方的组件中,例如保存到 Redis 中;但是不管是哪种方案,都让 Session 变成了项目的负担。
这时候,服务端就会想,如果 Session 不保存在我这里多好,第一次发送用户名密码给我,验证通过后我给你一个通行证,以后客户端每次请求的时候就带着这个通行证;
这个通行证就是 token,当然这个验证结果中需要包含客户端信息,服务端需要知道请求是谁发过来的;还需要包含时间信息,因为通行证不可能永远有效;通行证还不能是明文的,否则会有被截获的风险。
HMAC-SHA1:
- token = user_id|expiry_date|HMAC(user_id|expiry_date, k)
AES:
- token = AES(user_id|expiry_date, x)
RSA:
- token = RSA(user_id|expiry_date, private key)
05.SSO 单点登录
有些公司会建设统一登录系统(单点登录),客户端先去这个系统获取 Token ,验证通过再拿着这些Token去访问其他系统;API Gateway 也可以提供类似的功能,我们公司就是这样,客户端接入的时候,先向网关获取 Token,验证通过了才能访问被授权的接口,并且一段时间后要重新或者 Token。
06.Token 和 Session
对于 session 和 token ,对比它们没有本质的区别,两者都是加密后的字符串,都可以做身份验证。当然 token 比 session 还是有一定区别的,比如 token 跨域更容易,token 更好控制等等,另外在授权场景下,token 比 session 有着更大的优势;
比如,我开发一个网站,允许微信用户登录,使用 token 的流程大概是这样的:
- 登录网站时,跳转到微信登录页面;
- 用户输入用户名密码登录微信后,给我们一个 token;
- 用户拿着 token 就可以在我们的网站使用,而我们网站并不需要知道你微信的用户名和密码。
- 总之,如果在同一个网站内,token 和 session 并没有太大的区别,如果跨站使用,token 会更方便一些。
Cookie、Session 和 Token 就介绍这么多,如果有问题,大家可以加我微信或进微信群,咱们一起讨论。