什么是Token(令牌)
Acesss Token是访问资源接口(API)时所需要的资源凭证。
简单token的组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token的前几位以哈希算法压缩成的一定长度的十六进制字符串)
特点:
- 服务端无状态化、可扩展性好
- 支持移动端设备
- 安全
- 支持跨程序调用
token的身份验证流程:
- 客户端使用用户名跟密码请求登录
- 服务端收到请求,去验证用户名与密码
- 验证成功后,服务端会签发一个token并把这个token发送给客户端
- 客户端收到token以后,会把它存储起来,比如放在cookie里或者localStorage里
- 客户端每次向服务端请求资源的时候需要带着服务端签发的token
- 服务端收到请求,然后去验证客户端请求里面带着的token,如果验证成功,就向客户端返回请求的数据
每一次请求都需要携带token,需要把token放到HTTP的Header里。基于token的用户认证是一种服务端无状态的认证方式,服务端不用存放token数据。用解析token的计算时间换取session的存储空间,从而减轻服务器的压力,减少频繁的查询数据库。
另外还有一种token——refresh token,它是专用于刷新access token的token。如果没有refresh token,也可以刷新access token,但每次刷新都要用户输入登录用户名与密码,会很麻烦。有了refresh token,可以减少这个麻烦,客户端直接用refresh token去更新access token,无需用户进行额外的操作。Access Token的有效期比较短,当Acesss Token由于过期而失效时,使用Refresh Token就可以获取到新的Token,如果Refresh Token也失效了,用户就只能重新登录了。Refresh Token及过期时间是存储在服务器的数据库中,只有在申请新的Acesss Token时才会验证,不会对业务接口响应时间造成影响,也不需要向Session一样一直保持在内存中以应对大量的请求。
举个例子简单理解一下:
假设你去健身房锻炼:
Access Token 就像健身房的「单次门禁卡」,有效期1小时(短期有效)。有了它,你能进入健身房使用各种器材。
Refresh Token 就像「补办门禁卡的凭证」,有效期30天(长期有效)。当「单次门禁卡」过期后,你不用重新办卡(不用重新输入账号密码登录),直接用这个凭证就能免费换一张新的「单次门禁卡」。你第一次去健身房(首次登录),前台对你的身份(验证账号密码),给你一张「单次门禁卡」(Access Token)和一张「补办凭证」(Refresh Token)。而1小时后「单次门禁卡」过期了(Access Token失效):你不用再去前台重新登记(不用重新登录),直接出示「补办凭证」(Refresh Token),前台就会给你一张新的「单次门禁卡」(新的Access Token)。30天后「补办凭证」也过期了(Refresh Token失效):这时你必须重新去前台登记(重新登录),才能拿到新的「门禁卡」和「补办凭证」。
为什么需要这样设计?
- 如果只有Access Token且有效期很长:一旦被盗,别人可以长期冒用你的身份(不安全)。
- 如果只有短期的Access Token且没有Refresh Token:过期后需要频繁重新登录(体验差)。
- 有了Refresh Token:既保证了安全性(Access Token短期有效),又兼顾了便利性(不用频繁登录)。
Token和Cookie的区别
Cookie和Token虽然都能用于身份验证,但两者的设计逻辑和适用场景差异显著。Cookie 是互联网早期的产物,存在一些历史遗留问题,而Token更能适应现代Web开发的复杂需求,因此两者并非替代关系,而是根据场景互补使用。
Cookie是HTTP协议自带的状态传递工具,由浏览器自动存储和发送,默认与特定域名绑定,存在跨域限制,且容易因自动发送的特性带来CSRF等安全风险,存储容量也被限制在4KB左右,更适合简单的本地状态存储(如用户偏好)。而Token是服务器生成的加密令牌,完全由开发者控制存储位置(如localStorage、内存)和发送方式(如请求头),不受跨域限制,也不会被浏览器自动携带,能避免Cookie的默认行为带来的安全隐患,且可承载更多信息,更适合前后端分离、跨域API调用、移动端应用等场景。
Token和Session的区别
首先理解一下什么是Session:Session 是一种让服务器能够记录客户端(比如浏览器)会话状态的机制。当用户第一次访问服务器时,服务器会为这个用户创建一个独特的 Session,里面可以存储一些和该用户相关的信息,比如登录状态、购物车内容等。同时,服务器会生成一个对应的 SessionID,并通过 Cookie 等方式发送给客户端。之后,客户端每次向服务器发送请求时,都会带上这个 SessionID。服务器通过识别 SessionID,就能找到对应的 Session,从而知道这是哪个用户的请求,以及该用户之前的会话状态,这样就实现了服务端的“有状态”交互。
举个例子,你登录一个购物网站后,添加商品到购物车,这些操作记录会被保存在服务器为你创建的 Session 里。当你刷新页面或跳转到其他页面时,浏览器会自动带上 SessionID,服务器通过它找到你的 Session,所以购物车里的商品不会消失,这就是 Session 在起作用。不过,Session 是存储在服务器端的,这意味着如果服务器集群部署,需要考虑 Session 共享的问题,否则用户切换到集群中的其他服务器时,可能会因为找不到对应的 Session 而需要重新登录。
因而,Session是服务器用来记录和客户端之间会话状态的一种机制,它能让服务器处于有状态化,也就是能记住会话中的各种信息。而Token是一种令牌,是访问资源接口(API)时必须有的资源凭证,它能让服务器处于无状态的状态,不会去存储会话方面的信息。
Session和Token并不是相互冲突的。作为身份认证的方式,Token的安全性比Session更好,因为每一个请求都会带有签名,能够防止被监听以及重放攻击,而Session则必须依靠链路层来保证通讯的安全。如果需要实现有状态的会话,还是可以增加Session在服务器端保存一些状态信息。
所谓的Session认证,其实就是简单地把用户信息存储到Session里,由于SessionID难以预测,所以暂时可以认为它是安全的。而Token,如果指的是OAuth Token或者类似的机制,它能提供认证和授权功能,认证是针对用户的,授权是针对应用程序的。它的目的是让某个应用程序有权限访问某个用户的信息。这里的Token是唯一的,不能转移到其他应用程序上,也不能转到其他用户那里。Session只提供一种简单的认证,只要有了这个SessionID,就会被认为拥有该用户的全部权限。SessionID需要严格保密,只能保存在网站自己这边,不应该共享给其他网站或者第三方应用程序。所以简单来说,如果用户数据可能需要和第三方共享,或者允许第三方调用API接口,那就用Token。如果始终只是自己的网站、自己的应用程序,用哪种都没什么关系。