给 FastAPI 应用挂上令牌校验中间件
目标
直接在FastAPI应用程序上粘贴JWT验证中间件,分别用正确的状态代码区分没有令牌、过期、目标错误、权限不足的情况进行处理。
为什么重要
令牌验证中间件大部分用库解决,但如果给出错误的选项,就会悄悄通过。而且状态码区分也经常搞错——没有令牌或无效的话是401,令牌有效但权限不足的话是403。把这两者结合起来,客户端就无法区分“是否需要重新登录”和“是否需要请求权限”。第3步的JWKS缓存在实际工作中也很重要。每次向请求认证服务器询问公钥时,本地验证的好处就会消失。但无限缓存的话,密钥轮换后所有验证都会失败。缓存但kid如果找不到的话,一次性更新是标准的实现,在这个练习中直接制作它。
阶段
/root/app/main.py将127.0.0.1:8160上线。验证对象是事先导入的Relmlabhub和期待aud是lab-api是。用户是dev1(order-reader)和admin1(order-admin) 密码是/opt/fixtures/kc/realm-info.env在。GET /public没有这个认证就给200。GET /me在没有令牌的情况下调用的话,会返回401,并在回复中WWW-Authenticate必须要有标题。- 将JWKS缓存到内存中。
GET /_debug/jwks去{"cached":true,"keys":<n>,"fetches":<n>}给,/me调用了5次后fetches必须小于2。从这个步骤开始dev1的访问令牌/root/app/token.txt啊,admin1的/root/app/admin_token.txt逐行保存。 - 用有效的代币
GET /me呼叫的话,200和{"sub":"<값>","username":"dev1"}给。 - 用过期的令牌调用的话是401,在正文中
expired必须进去。到期代币是/opt/fixtures/kc/expired.jwt在。 aud用其他代币调用的话是401,在正文中audience必须进去。那种代币是/opt/fixtures/kc/wrongaud.jwt在。
5·6次的失败案例代币在帕德出现时/opt/fixtures/kc/gen-tokens.py创建。如果看不到两个文件,请直接运行一次该脚本——如果图片目录是只读的/tmp/lab-kc/在下面制作。
7. GET /admin银order-admin有卷的话是200,没有卷的话是403。不是401,而是403。
8. /root/app/e2e.sh依次测试五个案例(无代币、有效、过期、错误的aud、权限不足)。/root/app/e2e.out在no_token=401 valid=200 expired=401 bad_aud=401 forbidden=403写。
参考
- 401是“不知道是谁”,403是“知道是谁但没有权限”。
- JWKS缓存设置了TTL
kidMiss Si立即更新是标准。 - 时钟误差允许(leeway)设置在几秒以内非常小。
- 常见的错误1:给出401权限不足——客户端不必要地重新登录。
- 常见的错误2:依赖验证库
issuer哇audience不通过——只要签名正确就可以通过。
打开应用程序并确认公开端点
/root/app/main.py将127.0.0.1:8160上线。验证对象是事先导入的Relmlabhub和期待aud是lab-api是。用户是dev1(order-reader)和admin1(order-admin) 密码是/opt/fixtures/kc/realm-info.env在。GET /public没有这个认证就给200。
如果没有认证需要的路线,也需要有一个路线才能进行健康检查。
没有代币的话会给401
GET /me在没有令牌的情况下调用的话,会返回401,并在回复中WWW-Authenticate必须要有标题。
401 必须同时提供告诉您需要哪些认证的头衔。
实现JWKS缓存
将JWKS缓存到内存中。GET /_debug/jwks去{"cached":true,"keys":<n>,"fetches":<n>}给,/me调用了5次后fetches必须小于2。从这个步骤开始dev1的访问令牌/root/app/token.txt啊,admin1的/root/app/admin_token.txt逐行保存。
每次向请求认证服务器询问都会出现瓶颈。请缓存,但如果找不到密钥,请刷新。
通过有效的令牌
用有效的代币GET /me呼叫的话,200和{"sub":"<값>","username":"dev1"}给。
必须进行签名验证和索赔检查。请在回复中包含主体识别符。
拒绝到期的代币
用过期的令牌调用的话是401,在正文中expired必须进去。到期代币是/opt/fixtures/kc/expired.jwt在。
用过期时间点的代币进行测试。为了防止时钟误差,请留出非常小的余地。
拒绝错误的目标代币
aud用其他代币调用的话是401,在正文中audience必须进去。那种代币是/opt/fixtures/kc/wrongaud.jwt在。
即使是同一个服务器发行的,如果不是为我们的API准备的,也应该拒绝。
附上基于LOL的许可证
GET /admin银order-admin有卷的话是200,没有卷的话是403。不是401,而是403。
认证在进入点,授权在资源点进行。如果没有权限,不是401而是403。
一次验证五个案例
/root/app/e2e.sh依次测试五个案例(无代币、有效、过期、错误的aud、权限不足)。/root/app/e2e.out在no_token=401 valid=200 expired=401 bad_aud=401 forbidden=403写。
用一个脚本将前面的案例绑在一起,并与期望状态代码进行比较。