用户认证中的有状态和无状态
引言
我们在系统设计的时候,用户的认证是最基本也是最重要的功能了。我们常见的方案,就是将用户的认证信息保存到 session 里面。由于近年来微服务的快速兴起,一种 JWT 的认证方式出现在了大众的眼中。在单体服务的时代,很多系统设计的都是有状态的服务。随着微服务的出现,大多数系统设计的时候,都开始考虑无状态服务了。那它们的唯一区别,就是服务端是否会保存客户端的信息。简而言之,服务端保存了客户端的信息的这种状态的服务,就被称为有状态的服务,反之,就是无状态服务了。
有状态
有状态常见的模型就是 cookie - session 模型,这里就以 cookie - seesion 为例来说明有状态服务。
用户认证过程
1、客户端向服务端发起请求。
2、在第一次客户端发起请求的时候,服务端会创建一个 Key 为 session-id 的值,并保存在服务端同时写入到客户端的 cookie 中。
3、之后客户端的每次请求,都会将 cookie 信息发送给服务端,服务端会根据 cookie 进行判断。
优点
1、客户端的信息都保存在服务端,如果将客户端的认证信息删除,那么只需要将对应的 session 信息删除即可。
缺点
1、当用户量特别大的时候,服务端需要保存大量的 session 信息,会耗费大量的资源。
2、如果在服务端集群的情况下,session 的信息不能共享。
3、cookie 有同源策略和跨域限制,部分业务场景下 cookie 不能传递。
4、有些浏览器不支持 cookie 或禁用 cookie,部分手机浏览器不支持 cookie。
应用场景
如果以集群式的方式部署多台服务,可以使用以下策略:
1、配置负载均衡的路由策略为 hash 一致性算法,这种方式如何某个服务停了,那么会重新分配到新的机器,就又需要重新登录认证。(这种方式不推荐使用)
2、分布式 session 方式,这种方式可以将 session 保存到 redis 或者数据库中,提供给多个服务使用,实现 session 的集中管理。
如果有多个服务需要共享登录认证信息,可以使用 SSO 单点服务。
无状态
无状态的认证,服务端在验证客户端发送过来的请求信息之后,服务端根据一定的算法生成一个 Token 令牌返回给客户端。
客户端之后的每次请求都需要携带 Token 令牌,服务端接收到 Token 令牌之后进行校验,验证通过之后提取令牌中信息来识别用户。
无状态用户认证过程
1、客户端执行登录操作,发送账号密码等信息。
2、服务端校验客户端的用户信息,根据对应的用户信息和服务端密钥生成 Token 令牌,然后返回给客户端。
3、客户端在收到 Token 令牌之后,将其保存到本地的 LocalStorage。
4、以后的每次客户端发起请求时,都携带 Token 令牌。
5、服务端收到 Token 令牌之后,验证 Token 令牌的有效性和时效性,之后根据密钥解密参数信息。
优点
1、服务端不需要保留客户端的任何信息,每次只需要通过特定的算法进行校验,节省了大量的存储空间。
2、方便水平扩容,不需要 SSO 服务,只要保证新的服务采用同样的验证算法,就可以获得对应的信息。
缺点
1、当客户端的 Token 令牌被盗用,或者需要手动封禁某个用户的时候,无法对 Token 令牌进行操作,需要等到 Token 令牌失效。
2、如果在服务端维护一个 Token 令牌和用户的关系,又违背了无状态服务设计的理念。
应用场景
1、生成的 Token 令牌中携带用户的常用信息,不携带用户的敏感信息,例如:密码、手机号等,这些信息可以通过 BASE 64 解析处理。
2、要处理服务端主动禁用某个 Token 令牌,可以使用黑名单机制,每次请求前都判断当前 Token 令牌是否已经被写入黑名单。
3、Token 令牌中信息处理基本信息之外,还需要携带,例如:签发时间、有效时间、刷新 Token 令牌等字段,用来处理 Token 令牌刷新过期时间。
总结
在实际的系统设计中,需要充分理解需求,合理的使用技术,不同的技术方案适用不同的场景,技术存在即合理。
其他
1、目前大部分的互联网的产品中使用 JWT 的认证方式居多。
2、在一些企业内部的管理系统中采用 cookie - session 的居多。