投稿须知、干货分享浅度渣文程序猿进化之路

实现登录态的几种方式

2018-09-04  本文已影响9人  我是杨正

原文链接:https://www.dubby.cn/detail.html?id=9109

随着服务化的普及,直接维护session的越来越困难,现在一般来说都会使用一个token来表示用户的登录状态,用来标识这个用户的身份,这就是登录态。

登录态的解析一般就是入参是token,而返回结果是userId的方法(或服务、接口)。

一般来说,登录态校验的服务,QPS都会很大,因为大部分请求都需要依赖这个校验结果来做自己的业务逻辑。所以如果保证登录态解析的可靠性,和低延时是相当重要的。

这里我简单描述下我所知道的几种常见的实现方式。

1.存储型

存储型token,就是根据token这个字符串,可以在服务端存储上查到用户信息,那就是校验成功,如果查不到,那就是校验失败。

对于QPS很低的应用,可以使用MySQL来做存储,对于QPS很高的,可以使用Redis来做存储。这个方案的优势是,简单清晰,易于实现,且很自由,逻辑控制完全在服务端,比如踢谁下线、统计多少人登录,都一目了然;缺点是,这个解析的强依赖于这个存储,存储响应慢,那解析延时就高,存储可靠性低,那解析可靠性就不会高。虽说MySQL Cluster或者Redis Cluster已经很可靠的,但网络抖动,就真的无能为力了,网络一抖,解析就失败或超时。

且,成本其实很高的,每个用户的每次登陆,都需要在存储中记录一个数据,如果是MySQL还好,如果是Redis,那内存成本其实不小,感兴趣的可以自己算下。

2.计算型

计算型token,就是把用户信息如userId加密成一个字符串,这个字符串就是token,那么每次解析其实就是解密,解密出明文,比如userId,generateTimestamp,那么再根据generateTimestamp判断是否过期,如果解析都失败了,那就直接失败。

这个方案的优点是,性能很好,延时极低,且做到了真正的服务端无状态,不依赖任何外部存储,单看服务的话,可靠性几乎是最高的;但是缺点也很明显,完全依赖加密算法,那如果被破解,就完蛋了,这个可以考虑定期更换密钥,但是登录态信息完全放在客户端,服务端对的登录态的控制就很难了,比如踢谁下线,统计登录用户几乎不可能。

3.计算+存储

考虑到计算和存储的优劣势,我们可以考虑结合他们。这里举个例子token是个加密后的密文,解密后可以分成好几个字段,分别代表userId,generateTime,randomString。那么,如果解析都失败了,那就直接失败了,如果解析成功了,再根据generateTime来判断是否过期,如果过期了,那也直接失败了,如果都通过了,在拿randomString去存储中查询,以Redis为例,我们的存储结构可以设计成key是userId,value是sorted set,其中每个元素就是randomString,查得到就是合法,查不到就是非法。

优点是,那么在极端情况下,如果Redis访问失败/超时,那也可以退回成纯计算型token,暂时不去校验randomString,等Redis恢复后继续校验;缺点是,实现复杂。

说到这里可靠性其实已经很高了,但延时呢?

4.长短token

这里借鉴了缓存的概念,当然这里的缓存不是Redis。以PC为例,cookie里可以set两个,longToken,shortToken,其中longToken可以使用第三步说的计算+存储来实现,那么shortToken呢?每次校验登录态时,同时传入longToken,shortToken,如果没有shortToken,那么就去解析longToken,解析完之后如果成功,就生成一个新的shortToken给客户端;如果有shortToken,那么就去解析shortToken,shortToken完全使用加密的方式,如果shortToken解析成功就算成功。

需要注意shortToken的有效期一定要合适,这里的shortToken其实就是缓存,如果有效期合适的话,大部分请求都会由shortToken解析出来,避免了对存储的网络调用。如果有效期太长,会不安全,且踢出某个用户可能会有延时才能生效,有效期如果太短的话,那缓存效果可能不明显,所以需要结合业务特性来做决定。

上一篇下一篇

猜你喜欢

热点阅读