关联贴 https://v2ex.com/t/757713#reply20
看到楼里#37 老哥的讨论,很有收获,开个新帖说一下自己的理解,不知道对不对,大家轻喷。
之前跟群里老哥讨论,老哥说你这个做到最后会发现还是有状态的,我感觉则不是,我感觉按这个思路 jwt 是可以真正实现无状态的。简单来说我的逻辑是,jwt 唯一功能是保证 header 合法,合法的 header 里可能包含过期内容,这个 jwt 管不着。
但是通过建立黑名单的方式,可以管理 header 是否合法。也就是说合法的 jwt 保证 header 合法,header 又不在黑名单上,那说明 header 的一切都是对的,即使用户说我是超级管理员,那你说是那就是,不需要回源进行校验。
=====================================================
假设一个简单的业务场景,某用户 A 在第一天注册账号,在第二天手机丢失,理所当然地连带 jwt 一起丢失了,这时候他希望紧急改密码,防止损失扩散。
说一下个人理解的具体实现方法,为了方便理解假设全部 content 都使用明文,以“中心服务器”指代压力最后的数据节点,这个数据节点一直持有同步最新且正确的状态。
首先 A 注册并登录账号,过程中必然要使用到username=admin,password=12345678
的传输,业务节点也必然要请求数据端。请求验证通过后,服务端给 A 回复一个 header,内容为
{
username = admin
authlevel = 9
passwrod = 1234 //
}
密码放在 headers 里肯定要经过反复的单向 hash 与截断保证各级别的原始内容不泄露。
然后次日 A 的手机丢失,A 修改密码,此过程中中心服务器由它的请求附带 header 得知了要屏蔽的username+password
组合为admin+1234
,由此希望的行为是所有业务节点遇到该组合的 headers 时,拦截其请求。
那么中心服务器当然要维护一个黑名单,由于目前只有一个人改密码,所以黑名单长度为 1,内容为字符串 admin+1234, 并且同时中心服务器向所有业务节点分发一个状态机,这个状态机生成的过程是这样:
使用一些快速哈希算法,比如 fnv1-32/fnv1a-32/fnv1-64/fnv1a-64,
每个算法生成一个 mod512 的结果(对应即每种算法有 512 种可能的结果)
admin+1234 的对应结果为( 142/296/302/40 )
根据 Bloom Filter 原则,状态采用比特位累加,512 种可能性要采用 512bit 表示,
换算后正好为一个 64byte 的字符串,是 sha256 的原始长度,我们用四个这种长度的字符串即可表达该 hash 组合的对应结果。
针对目前这个特殊情况,这个长度为 256 的字符串中,18 位为'\x20',101 位为'\x80',166 位为'\x08',192 位为'\x80',其余全部为`\x00`
中心服务器同步状态后分发这个长度为 256bytes 的字符串,而从此以后业务节点在所有鉴权行为中,对 jwt 解码后,都要根据状态机校验他们的 user+pass 是否符合这个黑名单状态,如果不符合说明不在黑名单中,则 jwt 的内容可以完全信任,即便其中包含一些敏感信息,比如权限级别等等。这样避免了回源请求的开销。如果符合黑名单,那么仍有误判可能,回源进行请求。但由于 Bloom Filter 长度为 2048,在黑名单内容较少的条件下可以做到碰撞概率极低,黑名单内容较长的情况下可以做到直接校验通过大部分请求。由此可以缩减绝大部分业务节点回源请求的数量。
================================================
这样基本上实现了 jwt 设计的初衷即业务端点可以横向扩展而数据节点压力基本不会怎么增加。整个过程中后端同步状态的通信只发生在用户信息加入黑名单,和用户信息离开黑名单的时候,全局同步共两次,同步内容是长度为 256bytes 的字符串。
另外有关黑名单,由于 jwt 的 secret 有刷新机制,假设我们业务节点的 jwt 每半月刷新,即单个 jwttoken 的最大有效期为一个月。那么事实上黑名单只需要维护有效期为一个月即可。
以上只是一些各人构想,大家轻喷。v2 朋友知道我是做 pythonweb 技术栈的,在寻找 hash 算法过程中在 pypi 没有找到,所以顺带实现了一个 c 的版本,过两天放到 pypi 上。我本机测试延迟的话,这个额外 hash 校验的开销是比较低的,py 整个调用的延迟大概在几十纳秒的水平,可以认为其阻塞不对 python 的异步服务产生任何影响。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.