如何优化基于浏览器的 token 验证频率?

我用 react 写了几个页面,其中有几个页面是需要登录后才能够使用,我当前的判断方式是将获取到的 token 保存在浏览器的 localStorage 里,然后访问这些页面的时候,读取浏览器里是否有 token,然后将 token 发送到服务器验证。

我想请问,每次访问这些需要登录的页面,都会发一次到服务器做验证,这样的方式是不是太频繁了?还有其他更优越的方式吗?

阅读 944
2 个回答

额,这就属于你多想了,这算是 HTTP 的特性,因为其是无状态的,换句话说,如果没有 “Token” 一类的标识来进行区分,那对于服务器来说,每个请求都是 “陌生”。

如果没有 “Token” 服务器并不能知道,前一个请求跟后一个请求有什么关系,所以才需要每次都发送 Token 来证明:“你是你”。

况且,认证一个 Token 对于服务器来说,开销都很小。而对于客户端来说,传输的 Token 大小也没有什么可值得优化的。

对于类似于 JWT 的认证方式而言,甚至都不需要查库就能验证身份,而其他方式的也可通过缓存来减少 Token 的验证时间。

还有其他更优越的方式吗?

有,使用 Socket。这在浏览器环境下,有 WebSocket 可用,他的连接是有状态的,除非重新连接(一般发生的页面刷新后),当然,你也可以把它放到 Web Worker 里面,这样刷新页面也不影响,要发送请求的时候就从页面 postMessage 到 Worker 里面,然后 Worker 里面的 WS 再向服务端发送,但是,这样带来的麻烦就会变多了。

这些都是花活了,对于用户认证这个业务本身来讲,一般不太需要刻意的去做优化。

我理解为这个页面本身是纯静态的或不需要登录态的,只是需要验证用户是否已登录才能跳转进入而已,是这个意思吗?否则的话你也不需要一个单独的验证接口了。

如果是这样的话,可以考虑引入非对称加密机制,客户端(即前端)持有公钥,服务端(即后端)持有私钥。

登录后把你的 token、过期时间还有别的什么的字段让服务端使用私钥加密后返回给前端,前端自行持久化,这个东西我们叫它 credentials 或者别的什么玩意儿。

后续判断是否已登录,只需要前端尝试使用公钥解密 credentials、看是否能取得相应的结构。由于是非对称加密,只要你服务端的私钥不泄露,客户端自己就无法篡改该数据。所以只要能解密成功,那就可以视为已登录;反之则是未登录。这样一来验证是否登录的逻辑完全不依赖于服务端,直到 credentials 过期为止。

事实上服务端常见的 JWT 方案就类似于此,只不过它是利用数字签名,减少了服务端查 DB 的频率(因为一般认为瓶颈都在 DB 上),而不是减少客户端给服务端发请求的频率。但原理是相通的。

当然了,前提是你们业务上没有什么作废一个 token、踢用户下线之类的逻辑,否则上述流程无法满足实时验证登录状态的要求。“实时验证”跟“减少验证”本身就是冲突的。

推荐问题
宣传栏