token和session
前言
在介绍token和session之前,我们先了解一下无状态。http协议是一种无状态的协议,就是说服务器没有记忆能力,无法记住客户端之前有没有发送过请求,因此,客户端每次发送的请求都是独立的。但这会造成一个问题,当客户端中出现必须通过登录才能进行的操作时,每次请求都必须重复输入用户名和密码给服务器进行校验,频繁发送敏感的信息会造成很严重的安全问题。
那么针对以上存在的问题,是否存在某种方法,使得服务器能记住客户端的登录状态呢?
1、session
当用户登录时,发送用户名和密码后,服务端查询数据库是否存在该用户,如果有的话,会自动生成一个sessionid,用于记录登录的时间、状态、属于哪个用户,过期时间等信息,并将这些信息保存在服务端。同时,将这些信息通过cookie的形式将这些数据返回给客户端。当用户再次登录该服务器,访问其他接口的时候,会自动带上sessionid,服务器接收到请求后会自动查询有没有存储这个sessionid的信息。
通过上面我们可以知道,session解决了http无状态的问题,每次有新的用户访问服务器时,服务器都会自动存储用户信息。当存储数据量大,资源占用过多时,用户每次请求服务器都要花费相当多的时间去查询有没有sessionid。当系统涉及到多个服务器时,数据需要同步,那么就需要共享session,而cookie无法完成跨域。
那么有没有方法解决这些问题呢?
建立一个专用的数据库服务器,将session存储在一个数据库当中,但是当请求太多时,数据库的压力会非常大,一旦数据库挂了,就无法完成请求了。此时,需要建立数据库的集群,动态分配一个数据库去访问,保证响应速度。
session存在的问题:
- 存储在服务器,消耗大量的存储资源
- 查询速度会成为瓶颈,导致响应速度慢
- 在跨端、跨服务器时,需要session同步
- 通过架设数据库集群redis,会导致维护成本高,配置复杂
由于session会将用户登录的信息自动存储在服务端,导致存在某些问题,那么有没有一种方法:不保存用户登录信息,也能得到用户自己的状态和数据呢?
2、token
服务器不存储用户数据,而是直接通过加密的方式把用户数据通过令牌的方式返回给客户端,该令牌将会由服务器自己设置。每次用户访问时,都会携带这个令牌,用来证明自己的身份,从而得到自己的状态和数据。这样,服务器不需要存储用户资源导致资源占用过多的问题,也不需要每次查询从而加快了响应速度,而且传递的方式也由双方协定,不管是否跨域,都可以正常传递。
但是,上面的这种token容易被伪造,因为只要任何人拿到了这种令牌都可以称自己是合法的用户,从而获取一些私密的信息,此时如果服务器能拥有某种方式使得能证明该用户是合法的就显得极为重要。
sign:签名
它是由服务端进行设置,且只有服务器知道签名和密钥。当用户登录时,服务器提取将用户信息(payload)和header组成新的数据,然后再加上sign进行加密得到一个token。当用户发起请求后,由服务器对sign进行解密,然后再结合自己设置的sign进行对比,如果一致,就证明该token合法,如果不一致,该token就是非法的。
token
不需要将用户状态存储在服务端
消耗的是cpu,需要计算资源(验签)
token不能立即失效