[Wagtail] Topic: REST API Token
本篇章,为 [Wagtail] 01 - Headless CMS 的扩展。
Ref: https://www.django-rest-framework.org/api-guide/authentication/
一、Token, Session的两种 auth 的区别
Session 的缺点
1).session需要存在服务器内存中,这样就不能跨实例共享。当下一次请求被分发到另一个实例的时候,就会造成重新登录。
2).在高并发情况下,session放在内存中受限于内存的大小
3).session依赖于浏览器的cookie机制,对于移动客户端就很难支持,移动端使用的是 token。
Token 的优点
1). token方案保证了服务的无状态,所有的信息都是存在分布式缓存中。基于分布式存储,这样可以水平扩展来支持高并发。
2). 不依赖与cookie机制,可以通过客户端约定的协议来传输token,浏览器可以存在cookie中,手机端可以放在内存或者本地文件中,代价是增加了外部存储依赖以及在代码方面要复杂。
3) 可以在JWT中存储数据 Store Data in the JWT:我们知道,现通用的 Token-based Authentication 就是 JOSN Web Token (JWT)。JWT包含头部(header),载荷(claim set), 和签名(signature)。可以在载荷中存放预定义的元数据,只要是JOSON格式就可以了。
4) 不需要CSRF(cross-site-request-forgery)防护:由于不需要依赖Cookie,自然不用担心Cookie被截获,用户信息被伪造登陆问题。
Token 的问题
由于这里Token是后续用来登陆的唯一认证手段,如果用户关闭了网页,被其它别有用心的应用窃取到Token,拿它再来登陆就危险了。因此这里需要服务端给Tooken设置过期时间(expired time),不能太长,太长不安全;太短用户体验差。另外,当用户登出时,服务端要把当前Token设为黑名单(back list),防止被冒用。
二、Token 的原理
近年来,基于token的认证开始成为主流,不管是单个网页,还是web app,还是*Internet of Things *。该认证方式是无状态的(stateless),客户端登陆成功后,服务端会生成一个token并把它返还给客户端,由于是无状态的,服务端不再保存该Token。
问题来了,当客户端再发送请求时,服务端如何判断它曾经已经登陆了?
类似Sesssion based authentication,客户端每次发送请求时也会携带Token。由于这里的Token是服务端用自己的密钥签名的,当它受到客户端的Token时,只需要再用自己的密钥去验证,就可以判断这个Token是不是刚自己签发的。这里面的核心就是用签名和验证,从而减轻了服务端的负担,无需再存储session,尤其是对于大型的分布式应用,减负很多。以下是具体的过程:
-
- 客户端用自己的机密信息登陆,如用户名和密码
- 服务端验证,验证通过,生成Token返还给客户端(一般用哈希算法,再加个随机数)。
- 客户端把Token写入local storage(本地内存),后续请求都携带该Token
- 服务端收到请求时验证Token,如果验证通过,则允许用户访问相应资源
三、????